外星人(bzoj 2749)
Description
Input
Output
输出test行,每行一个整数,表示答案。
Sample Input
1
2
2 2
3 1
Sample Output
3
HINT
Test<=50 Pi<=10^5,1<=Q1<=10^9
br> 0<=beginlevel<=maxlevel
/* 这道题的60分暴力分还是很良心的。 观察题目给出的式子,我们可以发现phi(x)一定是偶数,则每次变换都会产生一些2,由此可以推断最后的答案就是2的个数。 我们设f(x)为最终答案,g(x)为x的分解过程中产生的2的个数则可以得到以下式子: g(x)=f(x)+1 (x是奇数) g(x)=f(x) (x是偶数) g(x)=g(phi(x))+1 g(p^q)=q*g(p-1) 那么就可以利用线性筛来解决这个问题 */ #include<iostream> #include<cstdio> #include<cstring> #define N 100010 #define lon long long using namespace std; int mark[N],prime[N],num,phi[N],g[N]; void get_prime(){ phi[1]=1; for(int i=2;i<N;i++){ if(!mark[i]) prime[++num]=i,phi[i]=i-1; for(int j=1;j<=num&&prime[j]*i<N;j++){ mark[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } for(int i=2;i<N;i++) g[i]=g[phi[i]]+1; } int main(){ get_prime(); int T;scanf("%c",&T); while(T--){ int m,flag=0;lon ans=0; scanf("%c",&m); for(int i=1;i<=m;i++){ int p,q;scanf("%c%c",&p,&q); if(p==2){ flag=1; ans+=(lon)q; } else ans+=(lon)q*(lon)g[p-1]; } if(!flag) ans++; cout<<ans<<endl; } return 0; }