【bzoj2749】[HAOI2012]外星人
2749: [HAOI2012]外星人
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 677 Solved: 360
[Submit][Status][Discuss]
Description
Input
Output
输出test行,每行一个整数,表示答案。
Sample Input
1
2
2 2
3 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 }