CF992C Nastya and a Wardrobe

我是题面

题意很清晰,这种题,我们当然还是有两种方法来做啦

方法一:找规律

读完题我们来看样例,通过样例一已我们大概可以看出,答案或许是(n*2^{k+1})

肯定不能这么简单对吧,那就来看样例二,难道答案是(n*2^{k+1}-k)或者是(n*2^{k+1}-2^{k-1})也有可能是(n*2^{k+1}-2^k+1)

通过样例三可得,答案是(n*2^{k+1}-2^k+1)

方法二:数学证明

每个月都是乘2,所以第i个月取走一个对第j个月的影响就是(2^{j-i}(i<j))

那么每个月都会对最后一个月产生影响,影响总和是$ sum _ {i=0} ^ {k-1} 2^i $,也就是(2^k-1)

这是负的影响,正的影响很容易算,就是(n*2^{k+1})

说白了,每个月要么直接乘二,要么-1再乘二,我们把这个-1提出来,就分成了上面所说的正贡献和负贡献

千万别忘了特判等于零,还有直接乘会爆long long

下面放代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#define ll long long
#define gc getchar
#define mo 1000000007
using namespace std;

inline ll read(){
	ll a=0;int f=0;char p=gc();
	while(!isdigit(p)){f|=p=='-';p=gc();}
	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
	return f?-a:a;
}

ll n,k,k1,e=2,sum=1;
inline ll cheng(ll a,ll b){
	ll sum=0;
	while(b){
		if(b&1)sum=(sum+a)%mo;
		a=(a<<1)%mo;b>>=1;
	}
	return sum;
}

int main(){
	n=read();k1=k=read();++k;
	if(n==0){
		puts("0");
		return 0;
	}k%=mo-1;
	while(k){
		if(k&1)n=cheng(n,e)%mo;
		e=cheng(e,e)%mo;k>>=1;
	}e=2;k1%=mo-1;
	while(k1){
		if(k1&1)sum=cheng(sum,e)%mo;
		e=cheng(e,e)%mo;k1>>=1;
	}
	--sum;if(sum<0)sum+=mo;
	printf("%lld
",((n-sum)%mo+mo)%mo);
	return 0;
}

不要抄代码哦

原文地址:https://www.cnblogs.com/hanruyun/p/10295777.html