Codeforces Round 976 (Div. 2)

B:

很容易发现只有因数个数为偶数的灯泡是亮的。所以只有完全平方数的因数是奇数个。
实现上可以二分。
但是sqrt是double的必须开sqrtl才是long double的,才能满足这题long long的数据范围。人给我卡傻了。哈哈。

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long

void solve(){
    int n,k;cin>>k;
    int l=1,r=1e19,mid=(l+r)/2;
    while(l<r){
        if(mid-floor(sqrtl(mid))<k)l=mid+1;
        else r=mid;
        mid=(l+r)/2;
        //if(mid<10)cout<<mid<<' '<<mid-floor(sqrt(mid))<<endl;
    }
    cout<<mid<<endl;
}
signed main(){
    int t=1;cin>>t;while(t--){
        solve();
    }
}

C

看到位运算题应该考虑每个位是否是独立的,如果是独立的就很容易可以按位处理了,这题就是如此。

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define pb push_back
#define pii pair<int,int>
#define mkp make_pair
const int maxn=2e5+10;
int b2[100],c2[100],d2[100],a[100];

void solve(){
    int b,c,d;cin>>b>>c>>d;
    for(int i=61;i>=0;i--){
        if((b>>i)&1)b2[i]=1;
        else b2[i]=0;
    }
    for(int i=61;i>=0;i--){
        if((c>>i)&1)c2[i]=1;
        else c2[i]=0;
    }
    for(int i=61;i>=0;i--){
        if((d>>i)&1)d2[i]=1;
        else d2[i]=0;
    }
    for(int i=61;i>=0;i--){
        if(d2[i]==1){
            if(b2[i]==0)a[i]=1;
            else a[i]=0;
        }
        else{
            if(b2[i]==1)a[i]=1;
            else a[i]=0;
        }
    }
    int p2=1,a2=0;
    for(int i=0;i<=61;i++){
        if(a[i])a2+=p2;
        p2*=2;
    }
    if((a2|b)-(a2&c)==d)cout<<a2<<endl;
    else cout<<-1<<endl;

}
signed main(){
    int t=1;cin>>t;while(t--){
        solve();
    }
}

D:

看题应该就知道是并查集
想到暴力处理会t,但是显然也不是数据结构,就很容易想到离线处理了。
注意到d很小因此可以采取n*d的递推做法。也就是每一个数最多能把他的状态更新给后面10个数

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int maxn=2e5+10;
int k[maxn][11],fa[maxn],n,m;
int find(int x){
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}

void solve(){   
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        fa[i]=i;
        for(int j=1;j<=10;j++)k[i][j]=0;
    }
    for(int i=1;i<=m;i++){
        int a,d,j;cin>>a>>d>>j;
        k[a][d]=max(k[a][d],j);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=10;j++){
            if(k[i][j]){
                k[i+j][j]=max(k[i+j][j],k[i][j]-1);
                fa[find(i+j)]=find(i);
            }
        }
    }
    for(int i=1;i<=n;i++)if(find(i)==i)ans++;
    cout<<ans<<endl;
}
signed main(){
    int t=1;cin>>t;while(t--){
        solve();
    }
}

E:

概率题。

用到的结论是概率的和等于和的期望。加法没有限制,乘法需要相互独立。
做法1:\(O(n*1024)\)
dp计算每个状态的概率可能即可。
做法2:\(O(n*11*11*8)\)
发现可以单独计算每一对位的的贡献。

posted @ 2024-09-30 10:02  lyrrr  阅读(35)  评论(0)    收藏  举报