Description
黑妹在玩游戏时又遇到了一个难题,这个游戏初始时给你 m m m个整数 x x x,黑妹需要构建一个长度为 n n n的数组使得该数组恰好包含这 m m m个整数,剩下的位置将由黑妹填上一些不大于 100 100 100的正整数,要求数组里任意相邻的两个整数互素。 黑妹轻松解决了这个游戏,但是她想知道具体有多少种方法构建这个数组。
由于答案可能很大,输出这个数对 1000000007 1000000007 1000000007取模后的值。
Input
第一行三个整数 n , x , m ( 1 ≤ n , x ≤ 100 , 0 ≤ m ≤ ⌊ n + 1 2 ⌋ ) n,x,m(1\le n,x\le 100,0\le m\le \lfloor\frac{n+1}{2}\rfloor) n,x,m(1≤n,x≤100,0≤m≤⌊2n+1⌋)
Output
输出答案对 1000000007 1000000007 1000000007取模后的值。
Sample Input
3 8 2
Sample Output
50
Solution
以
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示放好前
i
i
i个数字,已经用了
j
j
j个
x
x
x且第
i
i
i个数字是
k
k
k的方案数,枚举第
i
+
1
i+1
i+1个数
l
l
l,使得
g
c
d
(
k
,
l
)
=
1
gcd(k,l)=1
gcd(k,l)=1,进而有转移
d
p
[
i
+
1
]
[
j
]
[
l
]
+
=
d
p
[
i
]
[
j
]
[
k
]
,
l
≠
x
d
p
[
i
+
1
]
[
j
+
1
]
[
l
]
+
=
d
p
[
i
]
[
j
]
[
k
]
,
l
=
x
,
j
<
m
dp[i+1][j][l]+=dp[i][j][k],l\neq x\\ dp[i+1][j+1][l]+=dp[i][j][k],l=x,j<m
dp[i+1][j][l]+=dp[i][j][k],l̸=xdp[i+1][j+1][l]+=dp[i][j][k],l=x,j<m
∑
i
=
1
100
d
p
[
n
]
[
m
]
[
i
]
\sum\limits_{i=1}^{100}dp[n][m][i]
i=1∑100dp[n][m][i]即为答案
Code
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define maxn 105
#define mod 1000000007
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int T,n,m,x,dp[maxn][maxn][maxn],gcd[maxn][maxn];
int main()
{
scanf("%d%d%d",&n,&x,&m);
for(int i=1;i<=100;i++)gcd[0][i]=gcd[i][0]=i;
for(int i=1;i<=100;i++)
for(int j=1;j<=i;j++)
gcd[i][j]=gcd[j][i]=gcd[j][i%j];
dp[0][0][1]=1;
for(int i=0;i<n;i++)
for(int j=0;j<=m;j++)
for(int k=1;k<=100;k++)
if(dp[i][j][k])
for(int l=1;l<=100;l++)
if(gcd[k][l]==1)
{
if(l!=x)dp[i+1][j][l]=add(dp[i+1][j][l],dp[i][j][k]);
else if(j<m)dp[i+1][j+1][l]=add(dp[i+1][j+1][l],dp[i][j][k]);
}
int ans=0;
for(int i=1;i<=100;i++)ans=add(ans,dp[n][m][i]);
printf("%d\n",ans);
return 0;
}