题解 P6669 【[清华集训2016] 组合数问题】
发现
上面那个式子显然是一个
显然,如果
所以,问题就转化为了:给定
于是可以设计出一个数位 dp,用
代码仅供参考。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD = 1e9 + 7;
const int LOGN = 66;
LL k, n, m, bn[LOGN], bm[LOGN];
LL f[LOGN][2][2][2][2];
LL Solve(int cur, bool ok, bool dif, bool fn, bool fm)
{
if(!cur) return ok;
LL &res = f[cur][ok][dif][fn][fm];
if(~res) return res;
res = 0;
int upn = fn ? k - 1 : bn[cur], upm = fm ? k - 1 : bm[cur];
for(int i = 0; i <= upn; i++)
for(int j = 0; (j <= i || dif) && j <= upm; j++)
res = (res + Solve(cur - 1, ok | (i < j), dif | (i != j), fn | (i < upn), fm | (j < upm))) % MOD;
return res;
}
int main()
{
int t;
scanf("%d %lld", &t, &k);
while(t--)
{
scanf("%lld %lld", &n, &m);
memset(f, -1, sizeof f);
LL mx = max(n, m), len = 0;
while(mx) mx /= k, len++;
for(int i = 1; i <= len; i++) bn[i] = n % k, n /= k;
for(int i = 1; i <= len; i++) bm[i] = m % k, m /= k;
printf("%lld\n", Solve(len, false, false, false, false));
}
return 0;
}