poj2773 Happy 2006(用gcd函数进行的推导)

来源:互联网 发布:微处理器和单片机 编辑:程序博客网 时间:2024/06/14 06:30

这个题目本来是想学一下容斥原理  网上发现有人用二分答案和容斥原理做的。。。后来又发现了更简单的解法 直接用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;}


原创粉丝点击