Hard to prepare
题目来源
n个数字围成一圈,每个数字范围[0, ],问有多少种不同的序列满足对于所有相邻的两个数字,它们异或值不能为(二进制每个位不都为1),第一个数字和最后一个数字也算相邻。(0<n,k≤1e6) 。
存在两种情况
假设第1个数字有2^k种选择,第2到第n-1个数字均有2^k-1种选择(保证与前一个数不是互补),而第n个数字即不可以和第1个数冲突,又不能和第n-1个数冲突。那么此时的总方案数为:。
当第1个数与第n-1个数相同时,由于第n个数字少了一个冲突所以它有2^k-1种选择,所以上面对第n个数字少统计了一种情况,此情况方案就是求长度为n-2的序列(把第1个数与第n-1个数合并成一个后)的总方案数,递归
(注意cal_pow方法,暴力求会超时)
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<fstream>
#include<math.h>
#include<stack>
#include<queue>
#include<bitset>
#include<utility>
#include<set>
#include<map>
#define INF 0x7f7f7f7f
using namespace std;
typedef long long ll;
const int N=1000005;
const ll mod=1e9+7;
int t;
int n,k;
ll pow2[N];
ll cal_pow(ll r,ll x){
ll ans=1;
while(x)
{
if(x%2){
ans=ans*r%mod;
}
r=r*r%mod;
x>>=1;
}
return ans;
}
ll cal_ans(int an){
if(an==1){
return pow2[k];
}
if(an==2){
return pow2[k]*(pow2[k]-1)%mod;
}
ll ans=0;
ans=pow2[k]*cal_pow(pow2[k]-1,an-2)%mod*max((pow2[k]-2),(ll)0)%mod;
ans+=cal_ans(an-2);
ans%=mod;
return ans;
}
int main(){
scanf("%d",&t);
pow2[0]=1;
for(int i=1;i<N;i++){
pow2[i]=pow2[i-1]*2%mod;
}
while(t--){
scanf("%d%d",&n,&k);
printf("%lld\n",cal_ans(n));
}
return 0;
}