1. 程式人生 > >Jzoj P1161 機器人M號___尤拉函式+快速冪+dp

Jzoj P1161 機器人M號___尤拉函式+快速冪+dp

題目大意:

這裡寫圖片描述
1<=素因子個數<=1000
2<=素因子<10,000, 1<=指數<=1,000,000

分析:

①獨立數時小於等於的m與互質的數(包括1)
②一個數的老師是這個數的因數(不包括1)
xm的一個老師,
③政客:對於一個數x,如果x可以轉換為偶數個不同的素因子的積
④軍人:對於一個數x,如果x可以轉換為奇數個不同的素因子的積
⑤學者:既不是政客也非軍人,則為學者

一個數i的獨立數就是它的尤拉函式和,即ϕ(i)
f[i]表示在m所有大於2的素因子中選i個的尤拉函式和

政客的獨立數和為

(i)f[i]
軍人的獨立數和為(i)f[i]
而學者的獨立數和,
根據n=(d|n)ϕ(d)
mm
那麼我們通過快速冪求出p1e1p2e2....pkek,也就是m
那麼:學者的獨立數和,就是m軍人政客1

程式碼:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 1005 using namespace std; int p[N], f[N], ans, ans1, ans2, k, x, begin = 1, MOD = 10000; int ksm(int x, int y) { int cp = 1; for (; y; y >>= 1) { if (y & 1) cp = cp * x % MOD; x = x * x % MOD; } return cp; } int main() { scanf("%d", &k); ans = 1
; for (int i = 1; i <= k; i++) scanf("%d %d", &p[i], &x), ans = (ans * ksm(p[i], x)) % MOD; if (p[1] == 2) begin = 2; f[0] = 1; for (int i = begin; i <= k; i++) for (int j = i - begin + 1; j >= 1; j--) f[j] = (f[j] + f[j - 1] * (p[i] - 1)) % MOD; ans1 = ans2 = 0; for (int i = 1; i <= k - begin + 1; i++) if (i % 2 == 1) ans1 = (ans1 + f[i]) % MOD; else ans2 = (ans2 + f[i]) % MOD; ans = ((ans - ans1 - ans2 - 1) % MOD + MOD) % MOD; printf("%d\n%d\n%d\n", ans2, ans1, ans); return 0; }