1. 程式人生 > >【找規律】【遞推】【二項式定理】Codeforces Round #419 (Div. 1) B. Karen and Test

【找規律】【遞推】【二項式定理】Codeforces Round #419 (Div. 1) B. Karen and Test

main turn logs pow 分享 string ren () 奇數

打個表出來看看,其實很明顯。

推薦打這倆組

11

1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000

技術分享

12

1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000 100000000000

技術分享

打出表來看出來,n為偶數時,每隔兩行,對原序列的奇數項分配的權重形成二項展開式。

n為奇數時,每隔四行,形成二項展開式。

所以只需要求出接近最後的某一行中的二項式系數即可。(有個O(n)的遞推式可以直接求楊輝三角某一行的值)

最後距離答案已經不超過四行了,暴一下就行了。

#include<cstdio>
#include<cstring>
using namespace std;
#define MOD 1000000007ll
typedef long long ll;
ll n,nn;
ll a[200010],C[200010],b[10],c[10];
ll Quick_Pow(ll a,ll p)
{
    if(!p) return 1;
    ll ans=Quick_Pow(a,p>>1);
    ans=ans*ans%MOD;
    if((p&1)==1) ans=(a%MOD*ans)%MOD;
    return ans;
}
int main(){
	scanf("%I64d",&n);
	for(ll i=1ll;i<=n;++i){
		scanf("%I64d",&a[i]);
	}
	int tmp=0;
	if(!(n&1ll)){
		nn=n/2ll-1ll;
		tmp=2;
	}
	else{
		nn=n;
		++tmp;
		while((nn-1ll)%4ll!=0ll){
			--nn;
			++tmp;
		}
		nn/=2ll;
	}
	C[0]=1;
	for(ll i=1ll;i<=nn;++i){
		C[i]=((C[i-1]*(nn-(i-1ll)))%MOD*Quick_Pow(i,MOD-2ll))%MOD;
	}
	for(int i=1;i<=tmp;++i){
		for(int j=i,k=0;j<=n;j+=2,++k){
			b[i]=(b[i]+(a[j]%MOD*C[k])%MOD)%MOD;
		}
	}
	ll sum=0;
	for(ll i=n;i>(ll)tmp;--i){
		sum+=(i-1ll);
	}
	bool op=(sum%2ll==0 ? 1 : 0);
	for(int i=tmp;i>1;--i){
		for(int j=1;j<i;++j){
			if(op){
				c[j]=b[j]+b[j+1];
			}
			else{
				c[j]=b[j]-b[j+1];
			}
			op^=1;
		}
		memcpy(b,c,sizeof(c));
	}
	printf("%I64d\n",(b[1]+MOD)%MOD);
	return 0;
}

【找規律】【遞推】【二項式定理】Codeforces Round #419 (Div. 1) B. Karen and Test