这题其实也不难,但是坑点蛮多的
由 于 题 目 说 有 可 能 获 胜 就 行 , 所 以 只 要 连 续 传 送 带 不 多 于 10 个 就 合 法 由于题目说有可能获胜就行,所以只要连续传送带不多于10个就合法 由于题目说有可能获胜就行,所以只要连续传送带不多于10个就合法
Ⅰ . 当 多 于 10 个 , 无 论 如 何 无 法 通 过 这 片 区 域 就 会 回 退 \color{Red}Ⅰ.当多于10个,无论如何无法通过这片区域就会回退 Ⅰ.当多于10个,无论如何无法通过这片区域就会回退
Ⅱ . 不 多 于 10 个 , 由 于 每 次 扔 筛 子 , 总 有 办 法 不 经 过 一 次 传 送 带 到 达 终 点 \color{Red}Ⅱ.不多于10个,由于每次扔筛子,总有办法不经过一次传送带到达终点 Ⅱ.不多于10个,由于每次扔筛子,总有办法不经过一次传送带到达终点
那 么 定 义 d p [ i ] [ j ] [ q ] 为 截 至 到 i 个 格 子 放 了 j 个 传 送 带 , 且 目 前 连 续 放 了 q 个 传 送 带 那么定义dp[i][j][q]为截至到i个格子放了j个传送带,且目前连续放了q个传送带 那么定义dp[i][j][q]为截至到i个格子放了j个传送带,且目前连续放了q个传送带
如果决策在 i i i这个位置放传送,可以传送到的位置有 ∈ [ 1 , i − 1 ] \in[1,i-1] ∈[1,i−1],方案乘上(i-1)
Ⅰ . 那 么 当 q = 0 时 , d p [ i ] [ j ] [ q ] = ∑ s = 0 s = 10 d p [ i − 1 ] [ j ] [ s ] Ⅰ.那么当q=0时,dp[i][j][q]=\sum_{s=0}^{s=10}dp[i-1][j][s] Ⅰ.那么当q=0时,dp[i][j][q]=∑s=0s=10dp[i−1][j][s]
解 释 : 当 前 位 置 不 放 传 送 , 可 以 从 任 意 一 个 位 置 转 移 来 \color{Red}解释:当前位置不放传送,可以从任意一个位置转移来 解释:当前位置不放传送,可以从任意一个位置转移来
Ⅱ . 当 q = 1 时 , d p [ i ] [ j ] [ q ] = d p [ i − 1 ] [ j − 1 ] [ 0 ] ∗ ( i − 1 ) Ⅱ.当q=1时,dp[i][j][q]=dp[i-1][j-1][0]*(i-1) Ⅱ.当q=1时,dp[i][j][q]=dp[i−1][j−1][0]∗(i−1)
解 释 : 当 前 位 置 放 了 连 续 1 个 传 送 , 那 么 前 一 个 位 置 不 应 该 有 传 送 \color{Red}解释:当前位置放了连续1个传送,那么前一个位置不应该有传送 解释:当前位置放了连续1个传送,那么前一个位置不应该有传送
Ⅲ . 当 q ∈ [ 2 , 10 ] , d p [ i ] [ j ] [ q ] = d p [ i − 1 ] [ j ] [ q − 1 ] ∗ ( i − 1 ) Ⅲ.当q\in[2,10],dp[i][j][q]=dp[i-1][j][q-1]*(i-1) Ⅲ.当q∈[2,10],dp[i][j][q]=dp[i−1][j][q−1]∗(i−1)
解 释 : 放 传 送 且 接 着 上 次 的 连 续 传 送 \color{Red}解释:放传送且接着上次的连续传送 解释:放传送且接着上次的连续传送
但是这么开数组会炸,所以用滚动数组
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll n,t,m,dp[2][1009][12],ans,cha[1009][1009];
void DP()
{
//定义dp[i][j][q]为前i个格子放j个传送带,且当前连续放了q个传送带
dp[0][1][1]=1;
dp[0][0][0]=1;//初始状态其实是n=3的情况,此时只能在n=2的格子放或者不放
cha[2][1]=cha[2][0]=1;
for(int i=3;i<=1000;i++)//计算从在[2,n-1]区间内放j个传送带的情况
{
int t=i&1;//滚动数组
memset(dp[t],0,sizeof(dp[t]));
for(int j=0;j<=1000;j++)//到i格子放了j个传送带
{
if( j>0 )
dp[t][j][1]=dp[t^1][j-1][0]*(i-1)%mod;//新开一片区域放传送带,此时可以传送到前面的i-1个位置
for(int q=0;q<=10;q++)
{
dp[t][j][0]+=dp[t^1][j][q];//啥都不放,从所有状态转移而来
dp[t][j][0]%=mod;
}
for(int q=2;q<=10;q++)
{
if( j>0 )
dp[t][j][q]+=dp[t^1][j-1][q-1]*(i-1);
dp[t][j][q]%=mod;
}
}
for(int j=0;j<=1000;j++)//空间不够,开数组
for(int q=0;q<=10;q++)
{
cha[i][j]+=dp[t][j][q];
cha[i][j]%=mod;
}
}
}
int main()
{
scanf("%lld",&t);
DP();
while( t-- )
{
scanf("%lld%lld",&n,&m);
if( m==0 )
{
printf("1\n");
continue;
}
int s=(n-2)/(11);
int temp=s*10+(n-2)%11;
if( m>temp )
{
printf("-1\n");
continue;
}
//前面全都是特判
printf("%lld\n",cha[n-1][m]);
}
}