【思维】二进制模+预处理+暴力——atcoder AIsing Programming Contest 2020 D

这题细节真的多。。但是思维性还是蛮强的

一个数最多被操作logn次,所以可以预处理第一次操作,然后暴力解决

分类讨论下修改1的情况和修改0的情况,处理出前缀和和后缀和即可

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

char a[N];
int n,num,x,y,modx[N],mody[N],ans[N],pre[N],suf[N];


int calc(int x){//把x除到0需要的步数 
    int res=0;
    while(x){
        res++;
        int tot=0;
        for(int i=0;(1<<i)<=x;i++)
            tot+=(x>>i & 1);
        x%=tot;
    } 
    return res;
}

int main(){
    cin>>n;
    cin>>(a+1);
    
    for(int i=1;i<=n;i++)
        if(a[i]=='1')num++;
    if(num==0){//没有1的时候 
        for(int i=1;i<=n;i++)cout<<1<<'
';
        return 0;
    }
    if(num==1){//只有一个1的时候 
        if(a[n]=='1')
            for(int i=1;i<=n;i++)ans[i]=(i==n?0:2); 
        else 
            for(int i=1;i<=n;i++){
                if(a[i]=='1')ans[i]=0;
                else if(i==n)ans[i]=2;
                else ans[i]=1;
            }
        for(int i=1;i<=n;i++)cout<<ans[i]<<'
';
        return 0;
    }    
        
    
    x=num+1;y=num-1;//y>=1
    // 先把操作一次得到的结果求出来
     
    long long base=1;
    for(int i=n;i>=1;i--){
        base%=x;
        modx[i]=base;
        base*=2;
    }
    for(int i=1;i<=n;i++){
        if(a[i]=='1')pre[i]=modx[i]+pre[i-1];
        else pre[i]=pre[i-1];
        pre[i]%=x;
    }
    for(int i=n;i>=1;i--){
        if(a[i]=='1')suf[i]=modx[i]+suf[i+1];
        else suf[i]=suf[i+1];
        suf[i]%=x;
    }
    for(int i=1;i<=n;i++)if(a[i]=='0'){
        ans[i]=pre[i-1]+suf[i+1]+modx[i];
        ans[i]%=x;
    }
    
    base=1;
    for(int i=n;i>=1;i--){
        base%=y;
        mody[i]=base;
        base*=2;
    }
    for(int i=1;i<=n;i++){
        if(a[i]=='1')pre[i]=mody[i]+pre[i-1];
        else pre[i]=pre[i-1];
        pre[i]%=y;
    }
    for(int i=n;i>=1;i--){
        if(a[i]=='1')suf[i]=mody[i]+suf[i+1];
        else suf[i]=suf[i+1];
        suf[i]%=y;
    }
    for(int i=1;i<=n;i++)if(a[i]=='1'){
        ans[i]=pre[i-1]+suf[i+1];
        ans[i]%=y;
    }
     
    for(int i=1;i<=n;i++)
        cout<<calc(ans[i])+1<<'
';
}
原文地址:https://www.cnblogs.com/zsben991126/p/13285912.html