Description

对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程。

在可以选择的课程中,有 2n 节课程安排在 n 个时间段上。在第 i(1≤i≤n)个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 ci 上课,而另一节课程在教室 di 进行。

在不提交任何申请的情况下,学生们需要按时间段的顺序依次完成所有的 n 节安排好的课程。如果学生想更换第 i 节课程的教室,则需要提出申请。若申请通过,学生就可以在第 i 个时间段去教室 di 上课,否则仍然在教室 ci 上课。

由于更换教室的需求太多,申请不一定能获得通过。通过计算,牛牛发现申请更换第 i 节课程的教室时,申请被通过的概率是一个已知的实数 ki,并且对于不同课程的申请,被通过的概率是互相独立的。

学校规定,所有的申请只能在学期开始前一次性提交,并且每个人只能选择至多 m 节课程进行申请。这意味着牛牛必须一次性决定是否申请更换每节课的教室,而不能根据某些课程的申请结果来决定其他课程是否申请;牛牛可以申请自己最希望更换教室的 m 门课程,也可以不用完这 m 个申请的机会,甚至可以一门课程都不申请。

因为不同的课程可能会被安排在不同的教室进行,所以牛牛需要利用课间时间从一间教室赶到另一间教室。某天,当牛牛上完课来到下一间教室时,发现教室里空无一人,黑板上用白粉笔写着N个数字0和M个数字1,旁边贴着一个纸条,纸条上写着另一个整数K。

牛牛观察了一会儿,发现K−1竟然整除N+M−1!于是,好奇的牛牛想知道,如果称“在黑板上随机选择K个数擦掉,并把这K个数的平均数作为一个新的数写在黑板上”为一次操作,在他一直重复操作直到黑板上只剩一个数后,这个数有多少种可能的取值。显然,在这个过程中,黑板上的每个数都是有理数,牛牛是大学生,学过关于分数的知识,所以你不用关心他怎么如何把一个有理数写在黑板上。请你能帮助他统计这个数值,由于该数值过大,你只需要求出它对109+7取模的值就行了。

Input

输入第一行包含三个整数N,M,K。

Output

输出一个整数,表示黑板上最后的数字可能的取值数量对109+7取模的值。

Sample Input 1

2 2 2

Sample Input 2

3 4 3

Sample Input 3

150 150 14
Sample Output

Sample Output 1

5

Sample Output 2

9

Sample Output 3

937426930

HINT

在第一个样例中,5个可能的取值分别是1/4,3/8,1/2,5/8,3/4。其中,3/8可以通过以下方式得到:

  1. 擦去0和1,写上1/2。
  2. 擦去1/2和1,写上3/4。
  3. 擦去0和3/4,写上3/8。

数据范围:

1≤N,M≤2000,
2≤K≤2000,
K−1整除N+M−1。

存在10分的子任务,满足1≤N,M,K≤10。
存在30分的子任务(独立于上一个子任务),满足K=2。

思路

可以想象现在有一颗k叉树,然后一共有n+m个叶子节点,其中有n个为1,m个为0,每一个非叶子节点的值为所有儿子的平均数,问最后根节点有多少种不同的取值方案

这两者显然是本质相同的,因为每一个非叶子节点的值的获得相当于是k个数的合并

设n个为1的点深度分别为a1…an,0的深度为b1…bm,不妨把式子列出来:
∑ni=1k−ai+∑mi=1k−bi=1∑i=1nk−ai+∑i=1mk−bi=1
再设某一种方案的答案是z,那么又有:
z=∑ni=1k−aiz=∑i=1nk−ai
结合两条式子,我们发现一个z满足条件,当且仅当其可以表示成n个k次幂的和,且1-n可以表示成m个k次幂的和
不妨用k进制表示z
设z=0.c1c2c3…clz=0.c1c2c3…cl
如果不考虑进位的话,所有c的和就是n,那么如果考虑进位呢?
因为是k进制所以只要所有c的和%(k-1)==n%(k-1)就可以了
1-z也是类似的
这里我们规定cl不能为0,因为如果cl为0,1-z对应的数第l位也为0,和只有l-1位的情况就算重了
到这里应该就可以dp了,我觉得应该也不是很麻烦,主要是有一个进位的问题
但是题解还想再皮一下
cl一定不为0,那么1-z的第l位一定不为0,一定有一个bi为l
那么我们直接把这个bi提出来
那么要求的就变成了1−0.00…1=∑ni=1k−ai+∑mi=1k−bi1−0.00…1=∑i=1nk−ai+∑i=1mk−bi(k进制)
这样就不用考虑进位的问题
设f[i][j][0/1]表示当前做到小数点后第i位(深度为i),当前所有c的和(不取模,因为一共也不会超过n)为j,最后一位取的数为0/大于0
转移十分简单,前缀和优化即可做到nm

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+77,mod=1e9+7;
int n,m,K,i,j,k,q1,q2;
ll f[2][2077][2],sum[2077];
int ans;
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    m--; K--;
    q1=0;q2=1;
    f[0][0][0]=1;
    for(int i=1; i<=max(n,m)*2; i++)
    {
        for(int j=0; j<=n; j++) sum[j+1]=(sum[j-1+1]+f[q1][j][0]+f[q1][j][1])%mod;
        for(int j=0; j<=n; j++)
        {
            f[q2][j][0]=(sum[j+1]-sum[j-1+1])%mod;
            k=max(0,j-K);
            f[q2][j][1]=(sum[j-1+1]-sum[k-1+1])%mod;
        }
        for(int j=0; j<=n; j++) if(j%K==n%K&&(i*K-j)%K==m%K&&i*K-j<=m) ans=(ans+f[q2][j][1])%mod;
        q1^=1;q2^=1;
    }
    ans=(ans+mod)%mod;
    printf("%d",ans);
}