原本以为是数论知识,比赛的时候一直往那方面想,不过后来发现有些方面不能实现,结果比赛的时候就GG了。
优化的时间比没优化的时间快了快一倍,不过没优化也能卡过
/*
滚动数组。。。
dp[i+1][j+v][lcm[k][v]]+=dp[i][j][k];
*/
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define Maxn 1010
#define Mod 1000000007
int lcm[Maxn][Maxn];
int dp[2][Maxn][Maxn];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int LCM(int a,int b)
{
return (a*b)/gcd(a,b);
}
void Init()
{
int i,j;
for(i=1;i<1001;i++)
for(j=1;j<1001;j++)
lcm[i][j]=LCM(i,j);
}
int main()
{
int n,m,i,j,k;
Init();
int tt[Maxn];
while(~scanf("%d%d%d",&n,&m,&k))
{
int tot=0;
for(i=1;i<=m;i++)
{
if(m%i==0){
tt[tot++]=i;
}
}
int now=0;
for(int a=0;a<=n;a++) //初始化now
for(int b=0;b<tot;b++)
dp[now][a][tt[b]]=0;
dp[now][0][1]=1;
for(int t=0;t<k;t++)
{
now^=1;
for(int a=0;a<=n;a++) //初始化now
for(int b=0;b<tot;b++)
dp[now][a][tt[b]]=0;
for(i=;i<=n;i++) //初始和
for(j=0;j<tot;j++){ //初始lcm
if(dp[now^1][i][tt[j]]==0) continue;//上次状态不存在和为i,lcm为tt[j]这种情况
for(int z=0;z<tot;z++)
{
int x=i+tt[z];
int tmp=lcm[tt[j]][tt[z]];
if(x>n) continue;
dp[now][x][tmp]+=dp[now^1][i][tt[j]];
dp[now][x][tmp]%=Mod;
}
}
}
printf("%d\n",dp[now][n][m]);
}
return 0;
}