AtCoder AIsing Programming Contest 2020 D - Anything Goes to Zero (二进制,模拟)

-
题意:给你一个长度为\(n\)的\(01\)串,从高位到低位遍历,对该位取反,用得到的十进制数\(mod\)所有位上\(1\)的个数,不断循环直到为\(0\),输出每次遍历时循环的次数.
-
题解:根据题意,我们可以直接模拟来写,但是所给数据范围会TLE,我们先记所有\(1\)的个数为\(sum\),当取模时,我们要么取\(sum+1\),要么取\(sum-1\).然后我们要算出字符串对应的十进制数,而因为数据过大,我们要取模,这里我们算两种取模情况下的总值(\(sum+1\)和\(sum-1\)),然后再算某一位对应十进制的值(同样两种情况),用两个数组存下来,最后遍历的时候,我们直接暴力算:总值\(\pm\)(某一位)%(\(sum \pm 1\)).
-
代码:
int n; int sum; int add[N],sub[N]; int val_add,val_sub; int ans; string s; int fpow(int x){ int res=0; while(x){ res++; x%=__builtin_popcount(x); } return res; } int main() { ios::sync_with_stdio(false);cin.tie(0); cin>>n>>s; for(int i=0;i<n;++i){ if(s[i]=='1') sum++; } add[n-1]=1,sub[n-1]=1; for(int i=n-2;i>=0;--i){ if(sum!=1) sub[i]=2*sub[i+1]%(sum-1); add[i]=2*add[i+1]%(sum+1); } for(int i=n-1;i>=0;--i){ if(s[i]=='1'){ if(sum!=1) val_sub=(val_sub+sub[i])%(sum-1); val_add=(val_add+add[i])%(sum+1); } } for(int i=0;i<n;++i){ if(s[i]=='1'){ if(sum==1){ cout<<0<<endl; continue; } ans=(val_sub-sub[i])%(sum-1)+(sum-1); ans%=(sum-1); cout<<fpow(ans)+1<<endl; } else{ ans=(val_add+add[i])%(sum+1)+sum+1; ans%=(sum+1); cout<<fpow(ans)+1<<endl; } } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号