ABC304
A
略
B
题意:
给定一个n,让它区间为长度-3的后缀区间的位全部变为0
思路:
把数字看成字符串读入,然后模拟
void solve(){
string s;cin>>s;
int len=s.size();
int k=len-3;
s=" "+s;
if(k>0){
for(int i=len;i>=1;i--){
s[i]='0';
k--;
if(!k)break;
}
}
rep(i,1,len)cout<<s[i];
}
C
题意:
初始1号被感染,所有与被感染者距离不超过d的人也会被感染,求最终感染的人
思路:
利用队列模拟,把通过当前感染者感染的人放进队列。判断距离的时候,把欧几里得距离和d都平方在比较,避免sqrtl的精度丢失
int cal(int x1,int y1,int x2,int y2){
return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void solve(){
int n,d;cin>>n>>d;
vector<pii>a(n+1);rep(i,1,n)cin>>a[i].fi>>a[i].se;
vector<int>v(n+1);
v[1]=1;
queue<int>q;
q.push(1);
while(q.size()){
int now=q.front();q.pop();
// debug(now);
rep(i,1,n){
if(v[i])continue;
int x1=a[now].fi,y1=a[now].se;
int x2=a[i].fi,y2=a[i].se;
if(d*d>=cal(x1,y1,x2,y2)){
v[i]=1;
q.push(i);
}
}
}
rep(i,1,n){
if(v[i])cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
D
题意:
在二维平面上有n个草莓,分别横着切a次,竖着切b次,问切成的(a+1)(b+1)块中草莓数量的最小值和最大值
思路:
显然如果按块统计会超时
不妨看看按草莓统计,也就是看看每个草莓在哪个块中
考虑通过二分来查找 最靠近每个草莓的 右边线和上边线的下标,那么由于草莓不会在分割线上,显然它的左边线和下边线的下标为前两者-1
我们通过map<pair<pii,pii>,int>来进行草莓->块的映射
需要注意块内草莓可以为空,因此特判有草莓的块是否小于总块数
int w,h;
int n;
void solve(){
cin>>w>>h;
cin>>n;
vector<pii>a(n+1);
rep(i,1,n)cin>>a[i].fi>>a[i].se;
int x,y;cin>>x;
vector<int>b(x+1);rep(i,1,x)cin>>b[i];
cin>>y;
map<pair<pii,pii>,int>mp;
vector<int>c(y+1);rep(i,1,y)cin>>c[i];
rep(i,1,n){
int xx=a[i].fi,yy=a[i].se;
int p1=upper_bound(b.begin()+1,b.end(),xx)-(b.begin());
int p2=upper_bound(c.begin()+1,c.end(),yy)-(c.begin());
mp[{{p1-1,p1},{p2-1,p2}}]++;
}
int res1=llmax,res2=0;
int cnt=0;
for(auto [A,B]:mp){
// debug(B);
res1=min(res1,B);
res2=max(res2,B);
cnt++;
}
if(cnt<(x+1)*(y+1)){
res1=0;
}
cout<<res1<<' '<<res2<<endl;
}
E
题意:
给定一个拥有若干个连通块的好图G
给定一系列序偶,规定全部序偶的左键和右键代表的点如果都不连通,则称为好图
在G图的基础上,给定一系列查询,每次查询:判断连接给定点u和v,新图是否为好图
思路:
每个连通块可以用并查集维护,使得其可以被其中一个节点表示
可以知道:
如果连的是一个连通块内的点,那么生成的是好图
如果连的是两个连通块的点,那么这两个连通块若没有题目给定的关系,则生成的也是好图
可以考虑用map<int,set
int n,m,k,q;
vector<int>e[maxn];
int f[maxn];
int find(int x){
if(f[x]!=x){
f[x]=find(f[x]);
}return f[x];
}
void merge(int x,int y){
if(find(x)!=find(y)){
f[find(x)]=find(y);
}
}
int vis[maxn];
void solve(){
cin>>n>>m;
rep(i,1,n)f[i]=i;
rep(i,1,m){
int u,v;cin>>u>>v;e[u].pb(v);e[v].pb(u);
merge(u,v);
}
cin>>k;
vector<pii>a(k+1);
map<int,set<int>>mp;
rep(i,1,k){
cin>>a[i].fi>>a[i].se;
mp[find(a[i].fi)].insert(find(a[i].se));
mp[find(a[i].se)].insert(find(a[i].fi));
}
cin>>q;
while(q--){
int u,v;cin>>u>>v;
if(mp[find(u)].count(find(v))||mp[find(v)].count(find(v))){
cout<<"No"<<endl;
}else cout<<"Yes"<<endl;
}
}
F
题意:
给定一个长度为n的#.字符串S
以n的因子的作为循环节的长度构造另一个字符串T
规定每个S字符串为.的位置T位置都为#
求构造出的T字符串的种数
思路:
枚举n因子
将S所有为.的位置i考虑在内,显然对于循环字符串T,只需考虑第一个循环子串即可
那么i%len(循环串长度)位置都为#
其他位置可以为#亦可以为.,构造种数为2^cnt
考虑到重复情况
当在之前出现过len的因子,那么刚才计算的答案就包含了因子的答案,根据容斥原理,答案需要减去
最后的答案为所有因子的答案的累加
int ksm(int a,int b){
int res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}return res%mod;
}
void solve(){
int n;cin>>n;
string s;cin>>s;
vector<int>prime;
for(int i=1;i<n;i++){
if(n%i==0)prime.pb(i);
}
int ans=0;
vector<int>res(n+1);
for(int i=0;i<prime.size();i++){
int len=prime[i];
// int cnt=len;
vector<int>vis(len);
for(int j=0;j<n;j++){
if(s[j]=='.'){
vis[j%len]=1;
}
}
int cnt=0;
for(int j=0;j<len;j++){
if(vis[j])continue;
cnt++;
}
if(cnt>=0){
res[i]+=ksm(2,cnt);
for(int j=0;j<i;j++){
if(prime[i]%prime[j]==0){
res[i]=(res[i]-res[j]+mod)%mod;
}
}
ans+=res[i];
}
ans%=mod;
}
cout<<max(1ll,ans)<<endl;
}

浙公网安备 33010602011771号