(計蒜客 31453)ACM-ICPC 2018 徐州賽區網路預賽
阿新 • • 發佈:2018-12-24
題意:n個數字排成一圈,每個數字範圍[0, ],問有多少種不同的序列滿足對於所有相鄰的兩個數字,它們異或值不能為,其中第一個數字和最後一個數字也算相鄰。(0<n,k≤1e6) .
解析:①.首先易知第1個數字有2^k種選擇,第2到第n-1個數字均有2^k-1種選擇(保證與前一個異或值不能為0即可),而第n個數字即不可以和第1個數衝突,又不能和第n-1個數衝突。那麼此時的總方案數為:。
②.但是發現當第1個數與第n-1個數相同時,由於第n個數字少了一個衝突所以它有2^k-1種選擇,所以上面對第n個數字少統計了一種情況,此情況方案就是當把第1個數與第n-1個數合併成一個後的長度為n-2的序列的總方案數。
程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const ll MAXN=1e6+5; ll qpow(ll a, ll b) { ll ans=1; while(b) { if(b%2) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } ll pow2[MAXN],ans[MAXN]; ll solve(int n, int m) { ll ans; if(n==2) return pow2[m]*(pow2[m]-1)%mod; if(n==1) return pow2[m]; ans = (pow2[m]*qpow(pow2[m]-1,n-2)%mod*max(pow2[m]-2,0ll)%mod+solve(n-2,m))%mod; return ans; } int main(void) { int T,n,m,i; pow2[0]=1; for(i=1;i<MAXN;i++) pow2[i]=pow2[i-1]*2%mod; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); printf("%lld\n",solve(n,m)); } return 0; }