SDOI2010 代碼拍賣會
阿新 • • 發佈:2019-04-02
方程 line 題意 using 明顯 problem pre lin 傳送門 的數,當前數字模\(p\)為\(j\),已經選了\(k\)個\(111...111\)這樣的數字的方案數,轉移方程就是\(f[i][j][k] * \binom{cnt[i] + t - 1}{t} \to f[i + 1][(j + t \times i) \% p][k + t]\)。最後註意由於每一個數都是\(1\),所以\(1111...111\)(\(N\)個\(1\))是必選的。
SDOI2010 代碼拍賣會
題意:
題目傳送門
題解:
看完題目之後,第一反應應該就是數位\(Dp\)了,但是考慮到\(N\)非常的大,我們需要考慮另一種方法。註意到這個滿足條件的數字的每一位都大於等於前一位,所以我們可以比較明顯的發現,最後組成的數字一定可以表示成小於等於\(9\)個\(111...111\)(若幹個\(1\))這樣形式的數字之和,隨後可以發現這些數字在模\(p\)的意義下是有循環節的,所以我們可以設計一個\(Dp\),記\(cnt[i]\)表示模\(p\)為\(i\)的\(111...111\)這樣的數字的個數,\(f[i][j][k]\)表示考慮了模\(p\)小於等於\(i\)
Code:
#include <bits/stdc++.h> using namespace std; const int N = 505; const int Md = 999911659; typedef long long ll; inline int Add(const int &x, const int &y) { return (x + y >= Md) ? (x + y - Md) : (x + y); } inline int Sub(const int &x, const int &y) { return (x - y < 0) ? (x - y + Md) : (x - y); } inline int Mul(const int &x, const int &y) { return (ll)x * y % Md; } int Powe(int x, int y) { int ans = 1; for(;y; y >>= 1, x = Mul(x, x)) if(y & 1) ans = Mul(ans, x); return ans; } int f[N][N][10], cho[N][10], inv[10]; ll n; ll cnt[N], st[N], num[N]; int p, sum, St, Ed; int main() { scanf("%lld%d", &n, &p); for(int i = 1; i <= n; i++) { sum = sum * 10 + 1; sum %= p; if(st[sum]) { St = st[sum]; Ed = i; break; } cnt[sum]++; st[sum] = i; num[i] = sum; } int len = 0; if(St) { len = Ed - St; ll c = n - Ed + 1; ll d = c / len, m = c % len; for(int i = St; i < Ed; i++) cnt[num[i]] += d; for(int i = St; i < Ed && m; i++, m--) cnt[num[i]] ++; } cnt[0]++; inv[1] = 1; for(int i = 2; i <= 9; i++) inv[i] = Mul(Md - Md / i, inv[Md % i]); for(int i = 0; i < p; i++) { cnt[i] %= Md; cho[i][0] = 1; for(int j = 1; j <= 8; j++) { cho[i][j] = Mul(Mul(cnt[i] % Md, cho[i][j - 1]), inv[j]); cnt[i] = Add(cnt[i], 1); } } if(!len) { f[0][num[n]][0] = 1; for(int i = 0; i < p; i++) { for(int j = 0; j < p; j++) { for(int k = 0; k <= 8; k++) { for(int t = 0; t <= k; t++) { if(!f[i][(j - t * i % p + p) % p][k - t]) continue; f[i + 1][j][k] = Add(f[i + 1][j][k], Mul(f[i][(j - t * i % p + p) % p][k - t], cho[i][t])); } } } } printf("%d\n", f[p][0][8]); return 0; } int las = (n - Ed + 1) % len; if(!las) las += len; f[0][num[St + las - 1]][0] = 1; for(int i = 0; i < p; i++) { for(int j = 0; j < p; j++) { for(int k = 0; k <= 8; k++) { for(int t = 0; t <= k; t++) { if(!f[i][(j - t * i % p + p) % p][k - t]) continue; f[i + 1][j][k] = Add(f[i + 1][j][k], Mul(f[i][(j - t * i % p + p) % p][k - t], cho[i][t])); } } } } printf("%d\n", f[p][0][8]); return 0; }
SDOI2010 代碼拍賣會