2478:
思路:求欧拉函数
错误:用int的时候会溢出,要用64位
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1000005;
ll minDiv[maxn],phi[maxn];
void genPhi(){
for(int i=1;i<maxn;++i)
{
minDiv[i]=i;
}
for(int i=2;i*i<maxn;++i)
{
if(minDiv[i]==i){
for(int j=i*i;j<maxn;j+=i)
{
minDiv[j]=i;
}
}
}
phi[1]=1;
for(int i=2;i<maxn;++i)
{
phi[i]=phi[i/minDiv[i]];
if((i/minDiv[i])%minDiv[i]==0){
phi[i]*=minDiv[i];
}
else{
phi[i]*=minDiv[i]-1;
}
}
}
int main(){
// freopen("data.txt","r",stdin);
genPhi();
for(int i=2;i<maxn;++i)
{
phi[i]+=phi[i-1];
}
int n;
while(scanf("%d",&n)!=EOF&&n)
{
printf("%I64d\n",phi[n]-1);
}
return 0;
}
:3090:
题意:从原点向第一象限看去,有些点会被挡住(那些横纵坐标不即约的点),求能看到的点的个数
思路:欧拉函数代表了直线y=x一边可以看到的点,乘2就是两边可以看到的点,另外,(0,1),(1,1),(1,0)三个点不在里面,所以加上3
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1000005;
ll minDiv[maxn],phi[maxn];
void genPhi(){
for(int i=1;i<maxn;++i)
{
minDiv[i]=i;
}
for(int i=2;i*i<maxn;++i)
{
if(minDiv[i]==i){
for(int j=i*i;j<maxn;j+=i)
{
minDiv[j]=i;
}
}
}
phi[1]=1;
for(int i=2;i<maxn;++i)
{
phi[i]=phi[i/minDiv[i]];
if((i/minDiv[i])%minDiv[i]==0){
phi[i]*=minDiv[i];
}
else{
phi[i]*=minDiv[i]-1;
}
}
}
int main(){
// freopen("data.txt","r",stdin);
genPhi();
for(int i=2;i<maxn;++i)
{
phi[i]+=phi[i-1];
}
int n;
int C;
scanf("%d",&C);
int kase=0;
while(C--){
scanf("%d",&n);
printf("%d %d %I64d\n",++kase,n,(phi[n]-1)*2+3);
}
return 0;
}