POJ 3696 The Luckiest number(08合肥 数论)

来源:互联网 发布:网络刷到单诈骗怎么办 编辑:程序博客网 时间:2024/04/29 09:51

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove

题目:给出一个数n,找出他的一个倍数,而且这个数每一位都是8,找到最小的那个的位数,否则输出0.

http://poj.org/problem?id=3696 

其实是个挺有意思的数论,而且代码难度也不大。

但是可惜就是不会~~~~~~囧

8888888肯定可以写成8*(10^k-1)/9=m*n,n是原数字,k是位数。

稍微整理下8*(10^k-1)=9*n*m,令r=gcd(8,n)

则8/r*(10^k-1)=9*n/r*m。要使8/r*(10^k-1)是9*n/r的倍数,而且8/r与9*n/r互质,所以10^k-1==0(MOD 9*n/r)

即10^k==1 (MOD 9*n/r)。由欧拉定理知道,如果10与9*n/r互质,则10^phi(9*n/r)==1(mod (9*n/r)。

所以无解的情况就是不互质。

然后将phi(9*n/r)分解质因子,得到所有的约数,依次从小判断是否满足等式

注意9*n/r的最大范围为1.8*10^10,小心溢出,我还是用了高精度的模拟乘法

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#define N 80005#define maxn 150005#define LL long long#define pb(a) push_back(a) using namespace std;bool flag[N]={0};int cnt=0,prime[N];LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}void Prime(){for(int i=2;i<N;i++){if(flag[i]) continue;prime[cnt++]=i;for(int j=2;j*i<N;j++)flag[i*j]=true;}}LL get_eular(LL n){LL ret=1;for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++){if(n%prime[i]==0){ret*=prime[i]-1;n/=prime[i];while(n%prime[i]==0){n/=prime[i];ret*=prime[i];}}}if(n>1) ret*=n-1;return ret;}LL fac[N][2],tot;void Split(LL n){tot=0;for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++){if(n%prime[i]==0){fac[tot][0]=prime[i];fac[tot][1]=0;while(n%prime[i]==0){n/=prime[i];fac[tot][1]++;}tot++;}}if(n>1){fac[tot][0]=n;fac[tot++][1]=1;}}vector<LL>fact;void dfs(int idx,LL num){if(idx>=tot){fact.pb(num);return;}LL tmp=1;for(int i=0;i<=fac[idx][1];i++,tmp*=fac[idx][0])dfs(idx+1,num*tmp);}LL MultMod(LL a,LL b,LL MOD){      a%=MOD;      b%=MOD;      LL ret=0;      while(b){          if(b&1){              ret+=a;              if(ret>=MOD) ret-=MOD;          }          a=a<<1;          if(a>=MOD) a-=MOD;          b=b>>1;      }      return ret;  }  LL PowMod(LL a,LL b,LL MOD){LL ret=1;while(b){if(b&1) ret=MultMod(ret,a,MOD);a=MultMod(a,a,MOD);b>>=1;}return ret;}int main(){LL n;int cas=0;Prime();while(scanf("%I64d",&n)!=EOF&&n){LL p=(LL)9*n/gcd(8,n);printf("Case %d: ",++cas);if(gcd(10,p)!=1){printf("0\n");continue;}LL phi=get_eular(p);Split(phi);fact.clear();dfs(0,1);sort(fact.begin(),fact.end());for(int i=0;i<fact.size();i++){if(PowMod(10,fact[i],p)==1){printf("%I64d\n",fact[i]);break;}}}return 0;}