BZOJ 2749 HAOI 2012 外星人 数论 欧拉函数
题意:
给出一个数,给出的形式是其分解质因数后,对应的质因数pi及其次数qi,问对这个数不停求phi,直至这个数变成1,需要多少次。(多组数据)
范围:pi <= 1e5,qi <= 1e9
分析:
当x > 2时,phi[x]均为偶数。而每次求phi之后,2的次数只会减一,然后其他的质因数分解出多个2,因此数x分解得到的2的个数就是答案了。
如果一开始不存在质因数2,那么需要多进行一次phi操作。
程序:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <iostream> 7 8 using namespace std; 9 10 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i) 11 #define mset(a, b) memset(a, b, sizeof(a)) 12 const int maxn = 1e5; 13 typedef long long LL; 14 int prime[maxn+10], pcnt, g[maxn+10]; 15 bool isNotPrime[maxn+10]; 16 17 void prepare() 18 { 19 pcnt = 0, mset(isNotPrime, 0); 20 REP(i, 2, maxn) 21 { 22 if (!isNotPrime[i]) 23 { 24 prime[++pcnt] = i; 25 g[i] = (i == 2) ? 1 : g[i-1]; 26 } 27 REP(j, 1, pcnt) 28 { 29 if (i*prime[j] > maxn) break ; 30 isNotPrime[i*prime[j]] = true; 31 g[i*prime[j]] = g[i]+g[prime[j]]; 32 if (i%prime[j] == 0) break ; 33 } 34 } 35 } 36 37 int main() 38 { 39 prepare(); 40 int T; 41 scanf("%d", &T); 42 while (T --) 43 { 44 int m; 45 scanf("%d", &m); 46 LL ans = 0; int flag = 0; 47 while (m --) 48 { 49 int p, q; 50 scanf("%d %d", &p, &q); 51 flag |= (p == 2); 52 ans += (LL)g[p]*q; 53 } 54 printf("%lld\n", ans+(!flag)); 55 } 56 return 0; 57 }
Nothing is impossible!