| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 10751 | Accepted: 3744 |
Description
Now your job is easy: for the given integer m, find the K-th element which is relatively prime to m when these elements are sorted in ascending order.
Input
Output
Sample Input
2006 1 2006 2 2006 3
Sample Output
1 3 5
题意:求出与m互素的第k大的数
首先,介绍一个定理:若a与b不互素,则,tb+a与b也不互素,若a与b互素,则tb+a与b互素。所以,这个题目可以先求出m以内的与m互素的数,大于m的可以用l*m+a求出,其中a为小于m的与m互素的数,l为循环次数。
用欧拉函数求出循环长度,同时对m以内的素数(即大于m的素数%m的余数)进行标记
(吐槽一下,昨天用sublime打欧拉的模板打错了,在dev上改了过来,sublime上保存的依然是错的,今天拿着错误的模板wa了好多发……也是醉了)
#include <stdio.h>
#include<string.h>
long long m,k;
int pan[1000008];
long long phi(long long n)
{ long long m=n;
long long i,cnt,j;
cnt=n;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
for(j=i;j<=m;j=j+i)pan[j]=1;
cnt=cnt-cnt/i;
while(n%i==0)n=n/i;
}
}
//printf("n:%lld\n",n);
if(n>1){for(j=n;j<=m;j=j+n)pan[j]=1;cnt=cnt-cnt/n;}
return cnt;
}
int main(int argc, char const *argv[])
{ long long i,n;
while(~scanf("%lld%lld",&m,&k))
{ if(m==1){printf("%lld\n",k);continue;}
memset(pan,0,sizeof(pan));
long long f=phi(m);
// for(i=1;i<=m;i++)printf("%lld:%lld\n",i,pan[i]);
long long t=(k-1)/f;
long long p=(k-1)%f+1;
long long cnt=0;
for(i=1;i<=1000001;i++)
{
if(pan[i]==0)cnt++;
if(cnt==p){cnt=i;break;}
}
long long sum=cnt+t*m;
printf("%lld\n",sum);
}
return 0;
}
2186



被折叠的 条评论
为什么被折叠?



