思路 :dp[ i ] [ 0 ]表示 第i 位放的元音 dp[ i ] [ 1 ]表示 第i 位放的辅音 ,cnt [ i ]含义是 长度为 i 的方案数。
转移 :dp[ i ] [ 0 ] 由 上一个长度的所有方案数 也就是 cnt[ i-1 ] *5 转移而来 。
同理 dp[ i ] [ 1 ] 由 上一个长度的所有方案数 也就是 cnt[ i-1 ] *21 转移而来 。
但是 这是 无任何限制的情况下现在加了限制,连续 元音不超过 a 连续 辅音不超过 b
那么 首先 长度得 > a 或 > b 才会出现这种情况。 那么,当长度i = a +1 时 照常运算dp[ i ] [ 0 ] ,
但是需要减去 产生了 a + 1个元音相连的情况 。 也就是减去 dp[ i - a - 1][ 1 ] * pa 。pa是连续a+1 个元音的各种组合方案数
dp[ i - a - 1][ 1 ] 是去掉 a + 1的长度 之前 最后一个字母为辅音的状态。
同理 当长度i = b +1 时 照常运算dp[ i ] [ 1 ] ,但是需要减去 产生了 b + 1个元音相连的情况 。
也就是减去 dp[ i - b - 1][ 0 ] * pb 。pb是连续b+1 个辅音的各种组合方案数
dp[ i - b - 1][ 0 ] 是去掉 b + 1的长度 之前 最后一个字母为元音的状态。
不会 出现 a + 2 a + 3.....个元音相连,b+2,b + 3 .....个辅音相连 ,因为 a + 1个 元音相连 ,b +1 个辅音相连的情况,
都已经去掉了 ,长度一个一个增加不会产生 b + 2 ,a + 2 后面的也就更不会产生 。
ans 不断 求和 各个长度下的 方案数。
#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
#define ll long long
#define maxn 5678
ll pa,pb,dp[maxn][2],cnt[maxn],ans;
int t,n,a,b;
ll qpow(ll a,ll b)
{
ll ret=1;
while(b)
{
if(b%2)
ret=(ret*a)%mod;
a=(a*a)%mod;
b/=2;
}
return ret;
}
int main()
{
dp[0][0]=dp[0][1]=1;
dp[1][0]=5,dp[1][1]=21;
cnt[1]=26;
scanf("%d",&t);
while(t--)
{
ans=26;
scanf("%d%d%d",&n,&a,&b);
pa=qpow(5,a+1);
pb=qpow(21,b+1);
for(int i=2; i<=n; i++)
{
dp[i][0]=5*cnt[i-1]%mod;
dp[i][1]=21*cnt[i-1]%mod;
if(i>a) dp[i][0]=(dp[i][0]-dp[i-a-1][1]*pa+mod)%mod;
if(i>b) dp[i][1]=(dp[i][1]-dp[i-b-1][0]*pb+mod)%mod;
cnt[i]=(dp[i][0]+dp[i][1])%mod;
ans=(ans+cnt[i]+mod)%mod;
}
printf("%lld\n",ans);
}
return 0;
}