思路
没学过数论的同学估计一开始是不会想到欧拉函数的。
那么我们怎么去联想到这东西呢。
这道题,我们只需要计算y>x的点(上三角),然后答案就是2*ans+1了。(上三角+下三角+斜率为1的点)
我们现在通过找规律来看看n不同时斜率的一个情况(y/x):
n=1,ans=0;
n=2,ans=1,k=1/2
n=3,ans=2,k=1/3,2/3
n=4,ans=2,k=1/4,3/4(k=2/4已经被数过了)
...
凡是分子分母能约分的,前面都已经出现过,所以我们每次添加的数,分子分母都是互质的,
那么我们可以把问题转化为对于一个数n,求小于n且与n互质的数的个数,即求欧拉函数。
这样,我们就把二者结合起来了。
代码
#include<stdio.h>
const int maxn=10005;
bool isn_pri[maxn];
int phi[maxn],pri[maxn];
int n,ans,T,cnt;
void get(int x){
phi[1]=1;
for(int i=2;i<=x;i++){
if(!isn_pri[i]){
pri[++cnt]=i; //素数增加
phi[i]=i-1; //素数直接i-1
}
for(int j=1;j<=cnt&&i*pri[j]<=x;j++){
isn_pri[i*pri[j]]=1; //标记为合数
if(i%pri[j]==0){ //i可以分解
phi[i*pri[j]]=phi[i]*pri[j]; //利用积性函数的性质
break;
}else{
phi[i*pri[j]]=phi[i]*(pri[j]-1); //要积性再减去phi[i]个数,因为和pri[j]不互质
}
}
ans+=phi[i];
}
}
signed main(){
get(maxn-5);
scanf("%d",&T);
for(int t=1;t<=T;t++){
scanf("%d",&n);
ans=0;
for(int i=1;i<=n;i++) ans+=phi[i]; //只计算了下三角
printf("%d %d %d\n",t,n,ans*2+1); //下三角+上三角+斜率为1的点
}
return 0;
} 
京公网安备 11010502036488号