UESTC 1723

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define ll long long
#define inf 0x3f3f3f3f
#define N 1000005
#define MOD 1000000007
int n;
int prime[N],sum;
ll dp[N];
ll phi[N];
struct Zys//约数
{  
    int num,cnt;  
}zys[N];
int cnt;
void init()//筛选素数  
{  
    int i,j,flag;  
    prime[0]=2;  
    sum=1;  
    for(i=3;i<=1000000;i++)  
    {  
        flag=1;  
        for(j=0;j<sum&&prime[j]*prime[j]<=i;j++)  
        {  
            if(i%prime[j]==0)  
            {  
                flag=0;break;  
            }  
        }  
        if(flag)prime[sum++]=i;  
    }  
}  
void fj(int num)//分解n  
{  
    int i;
cnt=0;
    for(i=0;i<sum&&prime[i]*prime[i]<=num;i++)  
    {  
        if(num%prime[i]==0)  
        {  
            zys[cnt].num=prime[i];  
            zys[cnt].cnt=1;  
            num/=prime[i];  
            while(num%prime[i]==0)  
            {  
                zys[cnt].cnt++;  
                num/=prime[i];  
            }  
            cnt++;  
        }  
    }  
    if(num!=1)  
    {  
        zys[cnt].num=num;  
        zys[cnt].cnt=1;  
        cnt++;  
    }  
}
void mkphilist()//构造欧拉函数
{   
    int i,j;   
    phi[1]=1;  
    for(i=2;i<N;++i)   
    {  
        if(!phi[i])   
        {  
            for(j=i;j<N;j+=i)   
            {   
                if(!phi[j])phi[j]=j;   
                phi[j]-=phi[j]/i;   
            }   
        }  
    }
phi[1]=0;
    //以上是计算欧拉函数  

int pm(int x,int y)  
{  
    int ret=1;  
    while(y--)ret*=x;  
    return ret;  
}  
ll dfs(int dep,int num,int id)
{
if(dep==cnt)
{
return id/num*phi[num];
}
int i;
ll ret=0;
for(i=0;i<=zys[dep].cnt;i++)ret+=dfs(dep+1,num*pm(zys[dep].num,i),id);
return ret;
}
void Dp()
{
int i,j;
dp[1]=0;
for(i=2;i<N;i++)
{
fj(i);
dp[i]=dp[i-1]+dfs(0,1,i);
}
}
int main()
{
init();
mkphilist();
Dp();
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%lld\n",dp[n]);
}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值