题意就是有n个人围成圈,每个人能选择顶不同的帽子,但是相邻两个人选择的帽子的编号不能同或为0,问有多少种方案
按照第一直觉选择帽子,第1个人有种选择方案,第2到第n-1个人均有
种方案
第n个人的方案数取决于第1个和第n-1个人的帽子编号是否相同
相同时为种方案,不相同时有
种方案,总答案是两种情况求和,到此是第一直觉
但是我们忽略了交叉的情况,即第n-1个人的那种方案中包含了第n-1个人和第1个人的相同的情况和不同的情况
不同的情况是
和
相比少了一种,就是相同的那种,所以第n个人选择方案只有1种,相同时第n-1个人的选择和第1个人的相同,那么也是1种
到这儿我们发现第n个人确定后需要加上的方案数就是把n个人的规模减少到n-2个人的规模
所以递归即可
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll mod=1000000000+7;
const int N=1000000+5;
int t;
ll n,k;
ll pow2[N];
ll qp(ll a,ll b)
{
ll res=1;
while(b){
if(b%2) res=res*a%mod;
a=a*a%mod;
b/=2;
}
return res;
}
ll solve(ll n,ll k)
{
if(n==1) return pow2[k];//当只有1或者2个人时候直接返回答案
if(n==2) return pow2[k]*(pow2[k]-1)%mod;
return pow2[k]*qp(pow2[k]-1,n-2)%mod*(pow2[k]-2)%mod+solve(n-2,k);
//不同的情况加上相同的情况
}
int main()
{
pow2[0]=1;
for(int i=1;i<=1000000;i++)
pow2[i]=pow2[i-1]*2%mod;//预处理出2的幂次
scanf("%d",&t);
for(int kk=1;kk<=t;kk++){
scanf("%d%d",&n,&k);
printf("%lld\n",solve(n,k)%mod);
}
return 0;
}