哇 这个标题我以为是前一道题的加强版 结果没想到比第一题简单多了。
慢慢推出规律来
设输入的数为m
那么
注意这个和会爆int
因为long long wa了好几发。。。。
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
ll tt[1000005];
const int maxn=1e5;
int prime[maxn];
int vis[maxn],cnt,p;
void init()
{
cnt = 0;
memset(vis,0,sizeof(vis));
for(int i=2; i<maxn; i++)
{
if(!vis[i])
{
prime[cnt++]=i;
for(int j=i+i; j<maxn; j+=i)
vis[j]=1;
}
}
}
int quick(int m,int n)
{
int ans=1;
while(n)
{
if(n&1)
ans=ans*m;
m=m*m;
n>>=1;
}
return ans;
}
void init1(int m)
{
tt[1]=m-1;
for(int j=2; j<=m; j++)
{
int x=j;
int ans=1;
for(int i=0; prime[i]*prime[i]<=j; i++)
{
if(j%prime[i]==0)
{
int tmp=0;
while(x%prime[i]==0)
{
tmp++;
x/=prime[i];
}
ans*=(quick(prime[i],tmp+1)-1)/(prime[i]-1);
}
}
if(x>1)
{
ans=ans+ans*x;
}
tt[j]=tt[j-1]+m-ans;
}
}
int main()
{
int t,m;
scanf("%d",&t);
init();
while(t--)
{
scanf("%d",&m);
init1(m);
for(int i=1; i<=m-1; i++)
{
printf("%lld ",tt[i]);
}
printf("%lld\n",tt[m]);
}
return 0;
}