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 }
View Code

 

posted @ 2017-03-21 09:00  Splay  阅读(209)  评论(0编辑  收藏  举报