【bzoj2749】[HAOI2012]外星人

2749: [HAOI2012]外星人

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 677  Solved: 360
[Submit][Status][Discuss]

Description

Input

Output

输出test行,每行一个整数,表示答案。

Sample Input

1
2
2 2
3 1

Sample Output

3
 
 
 
【题解】
 
注意到只有phi[2]=1,所以每个数最终都是要经过phi[2]=1这一步变为1
 
而每一次做欧拉函数,从这个式子可以看出:会产生一个2,也必会消掉一个2
 
因此我们只需要算出原数N的质因子一共会产生多少个2即可
 
于是我们令f[i]表示i分解出了几个2:这一过程类似素数筛法
 
i为质数,f[i] = f[i - 1];否则,f[i * prime[j] = f[i] + f[prime[j]]  (<--这就是传说中的纯O(n)线性筛)
 
另:如果一开始n为奇数,则ans需+ 1,因为变出2需要第一步。
 
 1 /*************
 2   bzoj 2749
 3   by chty
 4   2016.11.4
 5 *************/
 6 #include<iostream>
 7 #include<cstdio>
 8 #include<cstdlib>
 9 #include<cstring>
10 #include<ctime>
11 #include<cmath>
12 #include<algorithm>
13 using namespace std;
14 #define MAXN 100000
15 typedef long long ll;
16 ll T,n,cnt,check[MAXN+10],prime[MAXN+10],f[MAXN+10];
17 inline ll read()
18 {
19     ll x=0,f=1;  char ch=getchar();
20     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
21     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
22     return x*f;
23 }
24 void pre()
25 {
26     f[1]=1;
27     for(ll i=2;i<=MAXN;i++)
28     {
29         if(!check[i])  {prime[++cnt]=i;  f[i]=f[i-1];}
30         for(ll j=1;j<=cnt&&prime[j]*i<=MAXN;j++)
31         {
32             check[prime[j]*i]=1;
33             f[prime[j]*i]=f[prime[j]]+f[i];
34             if(i%prime[j]==0)  break;
35         }
36     }
37 }
38 int main()
39 {
40     freopen("cin.in","r",stdin);
41     freopen("cout.out","w",stdout);
42     T=read();  pre();
43     while(T--)
44     {
45         n=read();  ll ans(1);
46         for(ll i=1;i<=n;i++)  
47         {
48             ll p=read(),q=read();
49             if(p==2)  ans--;
50             ans+=f[p]*q;
51         }
52         printf("%lld\n",ans);
53     }
54     return 0;
55 }

 

 
posted @ 2016-11-04 13:45  chty  阅读(227)  评论(0编辑  收藏  举报