当前位置:编程学习 > C/C++ >>

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

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

 


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

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

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

稍微整理下8*(10^k-1)=9*n*m,令r=易做图(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,小心溢出,我还是用了高精度的模拟乘法


[cpp]
#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 易做图(LL a,LL b){ 
    return b==0?a:易做图(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/易做图(8,n); 
        printf("Case %d: ",++cas); 
        if(易做图(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; 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,