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;
}
posted @ 2025-06-04 22:23  Marinaco  阅读(9)  评论(0)    收藏  举报
//雪花飘落效果