题意: 求与n互质的第k个数
开始看到这题很蒙 试了好几种做法都T了 后来才知道
由于GCD(a,b) = GCD(b, a%b) = GCD(a%b,b)
所以 GCD(a,b) = GCD(a+b , b) = GCD( (a+b) %b, b) = GCD( a+b*t,b)
本题可以把小于n于n互质的数都求出来 后面的于n互质的是都是前面第一周期(也就是小于n于n互质的数)+ n的倍数了
所以先求出k是第一周期的多少倍 用倍数× n再加上 第k对n取余个(第一周期的互质数)
注意结果有可能爆int
注意取余结果有可能是0 需要返回p-1倍+第一周期最有一个数
code:
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
const int lim = 1000005;
int z[lim];
ll gcd(ll a,ll b){return a%b==0?b:gcd(b,a%b);
}
int main()
{int n,k;while(~scanf("%d%d",&n,&k)){memset(z,0,sizeof(z));z[1]=1;int sze=1;for(int i=2;i<n;i++)if(gcd(i,n)==1)z[++sze]=i;ll p = k/sze;//注意int y = k%sze;if(y==0)p--,y=sze;//注意printf("%lld\n",p*n+z[y]);}return 0;
}
这道题还有一个做法 就是 二分那个第k个与n互质的数
利用容斥原理 去做二分查找的判定 那么这个与n互质的个数一定是随上界的上升而增多的
我们计算与n互质的个数 可以利用n-与n不互质的个数 = 与n互质的个数
找出n的所有因子 用 n - ( n/p1 + n/p2 +...n/pn - n/(p1*p2) -n/(p1*p3) - n/(p1*p4)...+n/(p1*p2*p3)+.....)
即可算出所有与n互质的数的个数
#include<iostream>
#include<cstdio>
#include<cctype>
#include<limits.h>
#include<vector>
using namespace std;
typedef unsigned long long ll;
const ll inf = LONG_MAX;
ll n,k;
ll sum;
vector<int>p;void devide(ll a)// 不必真的去那质数表分解 枚举分解法 因子也是质数
{for(int i=2;i*i<=n;i++){if(a%i==0){p.push_back(i);do a/=i;while(a%i==0);}}if(a>1)p.push_back(a);
}
void dfs(ll pos,ll now,ll cnt,ll x){//容斥计算if(pos==p.size()){if(now==1)return;if(cnt&1)sum+=x/now;else sum-=x/now;return;}dfs(pos+1,now*p[pos],cnt+1,x);dfs(pos+1,now,cnt,x);
}
bool test(ll x)
{sum=0;dfs(0,1,0,x);return (x-sum)>=k;
}
int main()
{while(~scanf("%d%d",&n,&k)){p.clear();devide(n);ll mid,l = 1,r = inf;if(k==1){printf("1\n");continue;}ll ans;while(l<r){ mid = (l+r)>>1; if(test(mid))r=mid;else l = mid+1; }printf("%lld\n",r);} return 0;
}