思路
没学过数论的同学估计一开始是不会想到欧拉函数的。
那么我们怎么去联想到这东西呢。
这道题,我们只需要计算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; }