POJ 2773 Happy 2006

来源:互联网 发布:2017东南大学软件学院 编辑:程序博客网 时间:2024/04/30 13:44

题意:找出第k(k<=100000000)个与一个数m(m<=1000000)互素的数。

先找出小于等于m的数中与m互素的数,对于大于m并且与m互素的数,都是由小于m且与m互素的数加上若干个m得到的。证明如下:

如果小于等于m且与m不互素的数,设为p,必然与m有大于1的最大公因子(设为r),p可以表示为p=r*a,m可以表示为m=r*b,其中a,b为整数,加上q个m后,p+q*m=r*(a+q*b),依然有大于1的公因子,所以p+q*m与m不互素。所以大于m并且与m互素的数,都是由小于m且与m互素的数加上若干个m得到的。

找小于等于m的数中与m互素的数,可以先把m的素因子找出来,然后与m互素的数必然不是这些素因子的倍数,就可以筛出来了。那么对于第k个互素的数,它等于(k-1)/len+prime[(k%len-1+len)%len]。其中,len代表小于等于m与m互素的数的个数。


代码:

#include <cstdlib>#include <cctype>#include <cstring>#include <cstdio>#include <cmath>#include<climits>#include <algorithm>#include <vector>#include <string>#include <iostream>#include <sstream>#include <map>#include <set>#include <queue>#include <stack>#include <fstream>#include <numeric>#include <iomanip>#include <bitset>#include <list>#include <stdexcept>#include <functional>#include <utility>#include <ctime>using namespace std;#define PB push_back#define MP make_pair#define REP(i,x,n) for(int i=x;i<(n);++i)#define FOR(i,l,h) for(int i=(l);i<=(h);++i)#define FORD(i,h,l) for(int i=(h);i>=(l);--i)#define SZ(X) ((int)(X).size())#define ALL(X) (X).begin(), (X).end()#define RI(X) scanf("%d", &(X))#define RII(X, Y) scanf("%d%d", &(X), &(Y))#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))#define DRI(X) int (X); scanf("%d", &X)#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)#define OI(X) printf("%d",X);#define RS(X) scanf("%s", (X))#define MS0(X) memset((X), 0, sizeof((X)))#define MS1(X) memset((X), -1, sizeof((X)))#define LEN(X) strlen(X)#define F first#define S second#define Swap(a, b) (a ^= b, b ^= a, a ^= b)#define Dpoint  strcut node{int x,y}#define cmpd int cmp(const int &a,const int &b){return a>b;} /*#ifdef HOME    freopen("in.txt","r",stdin);    #endif*/const int MOD = 1e9+7;typedef vector<int> VI;typedef vector<string> VS;typedef vector<double> VD;typedef long long LL;typedef pair<int,int> PII;//#define HOMEint Scan(){int res = 0, ch, flag = 0;if((ch = getchar()) == '-')//判断正负flag = 1;else if(ch >= '0' && ch <= '9')//得到完整的数res = ch - '0';while((ch = getchar()) >= '0' && ch <= '9' )res = res * 10 + ch - '0';return flag ? -res : res;}/*----------------PLEASE-----DO-----NOT-----HACK-----ME--------------------*/int factor[100];int vis[1000000+5];int prime[1000000+5];int main(){int m,k;while(RII(m,k)!=EOF){   int cnt=0;    int q=(int)(sqrt((double)m)+0.5);    int tmp=m;    for(int i=2;i<=q;i++)        if(tmp%i==0)    {        while(tmp%i==0)        {            tmp=tmp/i;        }        factor[cnt++]=i;    }    if(tmp!=1)        factor[cnt++]=tmp;    MS0(vis);    REP(i,0,cnt)    {        int p=m/factor[i]+1;        REP(j,1,p+1)        if((long long )(factor[i]*j)<=m)            vis[factor[i]*j]=1;    }    int cnt2=0;    REP(i,1,m+1)    if(!vis[i])        prime[cnt2++]=i;    long long int ans=(long long )((long long )(k-1)/cnt2*m+prime[(k%cnt2-1+cnt2)%cnt2]);    printf("%I64d\n",ans);}        return 0;}



0 0
原创粉丝点击