POJ 2773 Happy 2006 数学题

时间:2022-01-25 12:43:18

题目地址:http://poj.org/problem?id=2773

因为k可能大于m,利用gcd(m+k,m)=gcd(k,m)=gcd(m,k)的性质,最后可以转化为计算在[1,m]范围内的个数t。

1、AC代码:

开始的时候从1开始枚举if(gcd(n,i)==1),果断跑了2000ms

POJ 2773 Happy 2006 数学题

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <cfloat>
using namespace std; typedef __int64 LL;
const int N=1000002;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0); inline int in()
{
char ch = getchar();
int data = 0;
while (ch < '0' || ch > '9')
{
ch = getchar();
}
do
{
data=data*10+ch-'0';
ch=getchar();
}while(ch>='0'&&ch<='9');
return data;
} int xh[N]; int gcd(int n,int m)
{
int t;
while(m)
{
t=n%m;
n=m;
m=t;
}
return n;
} int main()
{
int i,j,n,k;
xh[1]=1;
while(cin>>n>>k)
{
if(n==1)
{
printf("%d\n",k);
continue;
}
int x=1;
for(i=2;i<n;i++)
{
if(gcd(n,i)==1)
xh[++x]=i;
}
int t=k%x,p=(k-1)/x;
if(t==0)
t=x;
printf("%d\n",p*n+xh[t]);
}
return 0;
}

2、AC代码

将于m互质的数记录下来。

POJ 2773 Happy 2006 数学题

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <cfloat>
using namespace std; typedef __int64 LL;
const int N=1000002;
const LL II=1000000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0); inline int in()
{
char ch = getchar();
int data = 0;
while (ch < '0' || ch > '9')
{
ch = getchar();
}
do
{
data=data*10+ch-'0';
ch=getchar();
}while(ch>='0'&&ch<='9');
return data;
} int xh[N];
LL pri[N],x;
bool vis[N]; void prime()//求素数
{
LL i,j;
x=0;
memset(vis,false,sizeof(vis));
for(i=2;i<N;i++)
{
if(!vis[i])
pri[++x]=i;
for(j=1;j<=x&&pri[j]*i<N;j++)
{
vis[pri[j]*i]=true;
if(i%pri[j]==0)
break;
}
}
} int main()
{
LL n,k,i,j;
prime();
while(scanf("%I64d%I64d",&n,&k)!=EOF)
{
LL q=n,sum=n;
if(n==1)
{
printf("%I64d\n",k);
continue;
}
memset(xh,0,sizeof(xh));
for(i=1;i<=x&&pri[i]*pri[i]<=n;i++)
{
if(n%pri[i]==0)
{
sum=sum*(pri[i]-1)/pri[i];
for(j=1;j*pri[i]<=q;j++)
xh[pri[i]*j]=1;//这个地方和上面的可能越界,所以要用__int64
}
while(n%pri[i]==0)
{
n/=pri[i];
}
}
if(n>1)
{
sum=sum*(n-1)/n;
for(j=1;j*n<=q;j++)
xh[j*n]=1;
}
//sum m以内与m互素的个数
LL t=k%sum,p=k/sum;
if(t==0)
{
t=sum;
p--;
}
LL temp=0;
for(i=1;i<=q;i++)
{
if(xh[i]==0)
temp++;
if(temp==t)
{
printf("%I64d\n",p*q+i);
break;
}
} }
return 0;
}