定义:
dp[ i ][ 0 ] 长度为 i ,首尾匹配的合法方案个数
dp[ i ][ 1 ] 长度为 i,首尾不匹配的合法方案个数
dp[ i ][ 2 ] 长度为 i,首尾相等的合法方案个数 = dp[ i-1 ][ 1 ]
转移方程见代码
坑点:m*m爆 int。取模意义下的减法需要加模数(尼玛错了n遍了。。。)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef int lint;
const LL mod = 1e9+7;
const lint maxk = 1000005;
LL mypow[maxk];
void prework(){
mypow[0]=1;
for( lint i= 1;i <= 1e6;i++ ){
mypow[i] = (mypow[i-1]*2)%mod;
}
}
LL dp[maxk][2];
void solve( lint n,LL m ){
dp[1][0] = m;dp[1][1] = m;
dp[2][0] = 0;dp[2][1] = m*(m-1)%mod;
for( lint i = 3;i <= n;i++ ){
dp[i][0] = (dp[i-1][0] + dp[i-1][1] - dp[i-2][1] + mod)%mod ;
dp[i][0] %= mod;
dp[i][1] = (dp[i-1][0]*(m-2))%mod + (dp[i-1][1]*(m-2))%mod + dp[i-2][1];
dp[i][1] %= mod;
}
}
int main(){
lint n,k,T;
scanf("%d",&T);
prework();
while( T-- ){
scanf("%d%d",&n,&k);
if( n == 1 ){
cout << mypow[k] << endl;
continue;
}
solve( n,mypow[k] );
cout << dp[n][1] << endl;
}
return 0;
}