Atcoder-AIsing Programming Contest 2020-D

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值