【題解】SDOI2008莎拉公主的困惑
阿新 • • 發佈:2018-02-05
color include 出現 std 打出 getchar col http urn
挺有趣的恩:洛谷P2155
在紙上打打草稿,寫出n!個數,從先往後,遇到不互質的就篩掉——發現一個奇妙的性質!:篩掉的次數、順序好像是周期性出現的呢~
而且更加妙妙的是,好像還是m!一輪..那麽因為n!一定能被m!整除,所以問題轉變為:(n!\m! - 有多少個循環節)*(φ(m))。
接下來,φ(m) = m!*(1 - 1/p1)*(1 - 1/p2)...任務就只剩下打出階乘表&逆元啦。離線的處理會快很多。
#include <bits/stdc++.h> using namespace std; #define maxn 10000050 #define ll long long #defineint long long int maxx, now = 1, P, T, tot, inv[maxn], ans[10050], pri[maxn],fac_a[maxn], fac_b[maxn], fac_c[maxn]; bool is_prime[maxn]; struct query { int n, m, id, pri; }Q[10050]; int read() { int x = 0; char c; c = getchar(); while(c < ‘0‘ || c > ‘9‘) c = getchar(); while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); return x; } bool cmp1(query a, query b) { return a.m < b.m; } int Get_Pri(int n) { for(int i = 2; i <= n; i ++) { if(!is_prime[i]) { pri[++ tot] = i; while(now <= T && pri[tot] > Q[now].m) { Q[now].pri= tot - 1; now ++; } } while(now <= T && i == n) { Q[now].pri = tot; now ++; } for(int j = 1; j <= tot; j ++) { if(i * pri[j] > n) break; is_prime[i * pri[j]] = 1; if(!(i % pri[j])) break; } } } int Get_fac(int n) { fac_a[0] = fac_a[1] = fac_b[0] = fac_b[1] = fac_c[0] = fac_c[1] = 1; inv[0] = inv[1] = 1; for(int i = 2; i <= n; i ++) { fac_a[i] = (fac_a[i - 1] * i) % P; inv[i] = ((P - P / i) * inv[P % i]) % P; } for(int i = 1; i <= tot; i ++) { fac_b[i] = inv[pri[i]]; fac_b[i] = (fac_b[i] * fac_b[i - 1]) % P; fac_c[i] = pri[i] - 1; fac_c[i] = (fac_c[i] * fac_c[i - 1]) % P; } } signed main() { T = read(), P = read(); for(int i = 1; i <= T; i ++) { Q[i].n = read(), Q[i].m = read(), Q[i].id = i; maxx = max(maxx, max(Q[i].n, Q[i].m)); } sort(Q + 1, Q + 1 + T, cmp1); Get_Pri(maxx); Get_fac(maxx); for(int i = 1; i <= T; i ++) ans[Q[i].id] = ((fac_a[Q[i].n] * fac_b[Q[i].pri]) % P * fac_c[Q[i].pri]) % P; for(int i = 1; i <= T; i ++) printf("%lld\n", ans[i]); return 0; }
【題解】SDOI2008莎拉公主的困惑