外星人(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;
}

 

posted @ 2017-03-13 22:27  karles~  阅读(230)  评论(0编辑  收藏  举报