0
点赞
收藏
分享

微信扫一扫

【vjudge contest 418548】2021 BUAA Winter Training 3(Private),签到题ABCDG

尤克乔乔 2023-02-08 阅读 49


题目

【vjudge contest 418548】2021 BUAA Winter Training 3(Private),签到题ABCDG_#include

A Amazing Pizza

/*
题意:给出一个圆环和n个圆,求多少个圆在圆环内
思路:先检查它是否在大圆内,再检查它是否在小圆外。
*/
#include<bits/stdc++.h>
using namespace std;
int main(){
double r, d; cin>>r>>d;
int n; cin>>n;
int ans = 0;
for(int i = 1; i <= n; i++){
double x, y, r1; cin>>x>>y>>r1;
double c = sqrt(x*x+y*y);
if(r-c>=r1 && c-(r-d)-r1>=0)ans++;
}
cout<<ans<<"\n";
return 0;
}

B Beware the Position

/*
+ n个人,每个人的位置为xi。m条信息,ri在li右边d的位置。
+ 求判断是否存在一组信息子集不冲突。
+ 以{l,r,d}为边建立有向图,跑一遍最短路,如果遇到冲突就No
*/
#include<bits/stdc++.h>
using namespace std;
struct node{int u, dist;};
int main(){
int n, m; cin>>n>>m;
vector<vector<node>>G(n);
for(int i = 0; i < m; i++){
int l, r, d; cin>>l>>r>>d;
l--; r--;
G[l].push_back(node({r, d}));
G[r].push_back(node({l, -d}));
}
vector<int>dist(n,-2e9);
for(int i = 0; i < n; i++){
if(dist[i]!=-2e9)continue;
dist[i] = 0;
queue<int>q;
q.push(i);
while(q.size()){
int t = q.front(); q.pop();
for(auto to:G[t]){
if(dist[to.u] == -2e9){
dist[to.u] = dist[t] + to.dist;
q.push(to.u);
}else{
if(dist[to.u] == dist[t] + to.dist)continue;
else {
cout<<"No\n"; return 0;
}
}
}
}
}
cout<<"Yes\n";
return 0;
}

C Beware the Position

/*
+ 题意:给出一个长为n的数组。现在将每个数k移至(k+a[k])%n,判断新产生的n个数是否会冲突
+ 思路:用set模拟,每次都加进去,最后既没有重复个数也相同就行。
*/
#include<bits/stdc++.h>
using namespace std;
int main(){
int T; cin>>T;
while(T--){
int n; cin>>n;
set<int>se;
for(int i = 0; i < n; i++){
int x; cin>>x;
se.insert(((i+x)%n+n)%n);
}
if(se.size()==n)cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}

D Divide and Conquer

/*
题意:
+ 存在一个长为n的01串,题目给出n。可以询问15次,确定01串中某个0和1的位置(题目保证存在)
+ 每次用一个长为n的01串提问,返回具有不同符号的位置数。
思路:
+ 第一次询问由全由0组成的串,得到的就是串中1的个数num1
+ 如果一个区间里只有0,那么构造一个只有区间[L,R]里面全是1,其他地方全是0的序列去询问的话,返回值req = num1+(R-L+1)。如果一个区间里只有0,那么构造一个只有区间[L,R]里面全是0,其他地方全是1的序列去询问的话,返回值req = num1-(R-L+1)。否则返回值就是介于之间的。
+ 此时可以二分答案,去找一个长度为2的"01"或"10"串。当[mid,R]中既有0又有1时L = mid,直到[L,R]区间长度为2为止。最后再询问一次就可以获得答案了。
*/
#include<bits/stdc++.h>
using namespace std;
int n, num1;
bool check(int L, int R){
string t = string(L-1,'0')+string(R-L+1,'1')+string(n-R,'0');
cout<<"? "<<t<<"\n";
fflush(stdout);
int req; cin>>req;
if(req>num1-(R-L+1) && req<num1+(R-L+1))
return true;
else
return false;
}
int main(){
cin>>n;
cout<<"? "<<string(n,'0')<<"\n";
fflush(stdout);
cin>>num1;

int L = 1, R = n;
while(R-L >= 2){
int mid = (L+R)/2;
if(check(mid,R))L = mid;
else R = mid;
}

string t(n,'0'); t[L-1] = '1';
cout<<"? "<<t<<"\n";
fflush(stdout);
int req; cin>>req;

cout<<"! ";
if(req==num1+1)cout<<L<<" "<<R<<"\n";
else cout<<R<<" "<<L<<"\n";
fflush(stdout);
return 0;
}

G Great Structure

/*
Atcoder, agc020_c
题意:
+ 给出一个长为n的序列,考虑所有(2^n-1)个非空子序列的和
+ 令这些和升序排列,输出它们的中位数。
思路:
+ 将序列等价于集合S,子序列就是非空子集A。对于每个A,它的补集要么是空集,要么也在S中。
+ 将两个互补的子集看做一组,那么每组中至少一个子集>=sum/2,另一个子集<=sum/2。
+ 所以这个序列的中位数就是第一个大于等于sum/2的子集,所以可以用01背包来解。
+ 因为V=4e6,N=2e3,VN=8e9,会超时,因为是二进制所以可以用bitset优化。因为dp[i]=max(dp[i],dp[i-ai]),所以左移的操作就可以做到这个目的。
+ 比如101011,ai=3,101011<<3=101011000,101011000|101011=10111011就相当于用ai更新了一次。
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 4e6+10;
bitset<maxn>b;
int main(){
int n; cin>>n;
int sum = 0;
vector<int>a(n);
for(int i = 0; i < n; i++){
cin>>a[i]; sum += a[i];
}

b[0] = 1;
for(int i = 0; i < n; i++)
b |= (b<<a[i]);

int ans = sum+1>>1;
while(b[ans]==0)ans++;
cout<<ans<<"\n";
return 0;
}


举报

相关推荐

0 条评论