[P3445] [POI2006] TAN - Dancing in Circles
更好的阅读体验
神仙题目!!!感谢程老师完成了几乎所有的证明过程。
首先注意到模数是
不难发现,把
设模数为
性质一:a_m \le p 。
考察等号左边的式子。若
性质二:\forall n \ge p ,a_m=p 。
考察等号右边的式子,记
记
性质三:记 q = \lfloor \frac{n}{p} \rfloor ,f(n,k) \equiv (-1) ^ q \times f(n ~ \text{mod} ~ p, k - q) ~ (\text{mod} ~ p) 。
由性质二,不难递归证明
由威尔逊定理可知,
由卢卡斯定理可知,
同样由卢卡斯定理可知,
所以
所以模
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n, k, l;
int f(int x, int y, int mod) {
static int dp[410][410], chs[410];
dp[0][0] = 1;
for (int i = l; i <= x; ++i) {
chs[i] = 1;
for (int j = i - l + 1; j < i; ++j) chs[i] = chs[i] * j % mod;
}
for (int i = 1; i <= y; ++i) {
for (int j = i * l; j <= x; ++j)
dp[i][j] =
(dp[i - 1][j - l] * chs[j] + dp[i][j - 1] * (j - 1)) % mod;
}
return dp[y][x];
}
int solve(int mod) {
if (l > mod) return 0;
int q = n / mod, r = n % mod;
if (q > k || (ll)(k - q) * l > r) return 0;
int ret = f(r, k - q, mod);
if (q & 1) ret = (mod - ret) % mod;
return ret;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k >> l;
int t1 = solve(5), t2 = solve(401);
while (t2 % 5 != t1) t2 += 401;
cout << t2 << "\n";
return 0;
}