標籤:names neu roc syn code ast str mod 逾時
http://codeforces.com/contest/852/problem/B
題意:有一幅有向圖,除了源點和匯點有 L 層,每層 n 個點。 第 i+1 層的每個點到 第 i+2 層的每個點都有一條邊,邊的權值為有向邊終點的權值。求源點到匯點的路徑長度能被 m 整除的個數。
題解:快速冪。a[i] 表示從第 1 層到第 a 層總路徑長度為 i (i % m) 的數目,b[j] 表示從第 a+1層到 第 a+1 層(也就是自己層)總路徑長度為 j (j % m) 的數目,那麼第 a+2 層的 a[(i+j)%m] = a[i]*b[j]。
暴力做法,從第一層開始,一層一層的乘上去,這樣顯然會逾時。
仔細看一下,從第 2 層到第 L-1 層,每次乘的操作是相同的,可以用快速冪先把第 2 層到第 L-1 層乘起來。
#include<iostream>#include<cstring>#include<algorithm>#include<cstdio> #define mod 1000000007using namespace std;const int MAXN = 100000+10;int a[1000010];int n, l, m;struct node{ long long num[110]; node() { memset(num, 0x0000, sizeof(num)); }};node Begin, End, mid;node mul(node la, node lb){ node aa = node(); for(int i = 0; i < m; i++) { for(int j = 0; j < m; j++) { int k = (i+j)%m; aa.num[k] += la.num[i] * lb.num[j] % mod; aa.num[k] %= mod; } } return aa;}node fast(node nod, int k){ node sum = nod; k--; while(k) { if(k&1) { sum = mul(sum, nod); } k >>= 1; nod = mul(nod, nod); } return sum;}int main (void){ ios::sync_with_stdio(false); Begin = node(); End = node(); mid = node(); cin >> n >> l >> m; for(int i = 1; i <= n; i++) { int x; cin >> x; Begin.num[x%m]++; } for(int i = 1; i <= n; i++) { int x; cin >> x; a[i] = x; mid.num[x%m]++; } for(int i = 1; i <= n; i++) { int x; cin >> x; End.num[(x+a[i])%m]++; } node nod; if( l-2 > 0 ) { nod = fast(mid, l-2); nod = mul(nod, Begin); nod = mul(nod, End); } else { nod = mul(Begin, End); } long long ans = 0; for(int j = 0; j <= 100; j++) { if(j%m==0) { ans += nod.num[j]; ans %= mod; } } cout << ans;}
codefroces 852B - Neural Network country