这个题目本来是想学一下容斥原理 网上发现有人用二分答案和容斥原理做的。。。后来又发现了更简单的解法 直接用gcd函数进行推导。。
题意就是给出m 和k m最大100w k最大 1亿
现在要求从1 开始 第k个 与m互素的数。
我们看gcd函数
gcd(a,b)=gcd(a%b,b)=gcd(a+b,b);
因为 a%b 和 (a+b)%b 是相等的。
这里能看出什么?
在 1-m 这个区间 和 m+1 到2m 这个区间
看 gcd(a,m) 和 gcd(a+m,m); 肯定是相当的 也就是说 以m为周期 互素的个数是一样的。
那么我们只要求出 1到m之间 与 m互素的数。
然后对于k 首先要k-- 因为 prim数组是从0到n的 k首先得--才能算出 就比如n=10,如果k是20 应该是一个周期 加上 prim的最后一个元素 也就是 19/10 +prim[9];
如果k是19 就是 18/10+prim[8];
之后找出有多少个周期。 就是 (k/n)*m 再在这个基础上 加上 prim[k%n] 就得到了。。注意用long long;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxm=1000005;
const int maxk=100000005;
int prim[maxm];
int gcd(int a,int b)
{
if(a==0) return b;
else return gcd(b%a,a);
}
int main()
{
int m,k;
while(scanf("%d %d",&m,&k)!=EOF)
{
if(m==1)
{
printf("%d\n",k);
continue;
}
int n=0;
for(int i=1;i<m;++i)
{
if(gcd(i,m)==1)
prim[n++]=i;
}
k--;
printf("%lld\n",(LL)k/n * (LL)m +prim[k%n]);
}
return 0;
}