传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2227
首先,总的方案数很好求,为k^n,但合法的方案就蛋疼了,我们试着将问题转化一下,令一个方案始终合法,我们添加一个新位置将原序列首尾相连,
这样无论如何就合法了,方案数为(k + 1) ^ (n - 1),最后我们枚举在哪里断开,方案为(k - n + 1),于是ans = (k + 1) ^ (n - 1) * (k - n + 1) / k ^ n
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 1010; struct node { int a[maxn]; node() { memset(a, 0, sizeof(a)); a[0] = a[1] = 1; } void cr() { memset(a, 0, sizeof(a)); a[0] = a[1] = 1; } void operator *= (int t) { for(int i = 1; i <= a[0]; i ++) { a[i] *= t; } for(int i = 1; i <= a[0]; i ++) { a[i + 1] += a[i] / 10; a[i] %= 10; } int k = a[0] + 1; while(a[k]) { a[k + 1] += a[k] / 10; a[k] %= 10; k ++; } k --; a[0] = k; } void operator /= (int t) { int res = 0; for(int i = a[0]; i ; i --) { res = res * 10 + a[i]; a[i] = res / t; res %= t; } int k = a[0]; while(k > 1 && !a[k]) k --; a[0] = k; } void print() { for(int i = a[0]; i ; i --) { printf("%d", a[i]); } } }ans1, ans2; int t, n, k; int gcd(int a, int b) { if(!b) return a; return gcd(b, a % b); } int main() { scanf("%d", &t); while(t --) { ans1.cr(); ans2.cr(); scanf("%d%d", &n, &k); if(n > k) { printf("0 1\n"); continue; } int p = k - n + 1, w = 1; for(int i = 1; i <= n; i ++) { int q = gcd(p, k); w *= q; p /= q; } for(int i = 1; i < n; i ++) ans1 *= (k + 1); for(int i = 1; i <= n; i ++) ans2 *= k; ans1 *= (k - n + 1); ans1 /= w; ans2 /= w; ans1.print(); printf(" "); ans2.print(); printf("\n"); } return 0; }