Anything Goes to Zero
题意:给定一个二进制串,按位计算,计算每一位时,取反,得到一个二进制数,用其取余其二进制下1的个数,得到结果,再执行同样的取余步骤,直到结果为0,输出所需的步数。
做法:每一位取反,在二进制下1的个数,就是整体串中1的个数加一或减一,先预处理出不取反时的结果,然后每一位判断,加上或减去该位的变化,计算结果即可。
简单来说就是:先这样,再这样,然后这样,最后输出就好了。
切记快速幂时,数据类型定义为longlong,不然就会乘炸了(因题而定)。比赛时没开longlong到比赛结束也没过,一直改一直改,wa了无数发。
_builtin_popcount()计算二进制中多少个1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
int a[N];
int lis[N];
int falg1[N],falg2[N];
ll quick(ll a,ll b,ll mod) {
int ans=1%mod;
a%=mod;
while(b) {
if(b&1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans%mod;
}
int main() {
int n;
scanf("%d",&n);
int sum=0;
for(int i=1; i<=n; ++i) {
scanf("%1d",&a[i]);
sum+=a[i];
}
if(sum>1) {
ll cut0=0,cut2=0;
for(int i=1; i<=n; ++i) {
if(a[i]==1) {
cut0=(cut0+quick(2,n-i,sum-1))%(sum-1);
cut2=(cut2+quick(2,n-i,sum+1))%(sum+1);
}
}
for(int i=1; i<=n; ++i) {
ll ans=0;
int cut=1;
if(a[i]==0) {
ans+=cut2;
ans=(ans+quick(2,n-i,sum+1))%(sum+1);
} else {
ans+=cut0;
ans=(ans-quick(2,n-i,sum-1)+(sum-1))%(sum-1);
}
while(ans>0) {
ans=ans%__builtin_popcount(ans);
cut++;
}
printf("%d\n",cut);
}
} else if(sum==0) {
for(int i=1; i<=n; ++i) {
printf("1\n");
}
} else {
for(int i=1; i<=n; i++) {
if(a[i]==1) {
printf("0\n");
} else {
if(a[n]==1||i==n)printf("2\n");
else printf("1\n");
}
}
}
return 0;
}