1. 程式人生 > >The Luckiest number POJ - 3696 (尤拉定理)

The Luckiest number POJ - 3696 (尤拉定理)

題目大意:對於給定的整數L,找出L能整除最短的全8序列的長度,做為Bob的幸運數字。

解析:一開始做這個題的時候直接莽夫式做法 ,列舉8的位數,交一發直接wa,想想也是,沒給8的位數的上限,暴力列舉8的話肯定要爆longlong的。 。。

正確的做法居然是用尤拉定理。我們可以通過題意列出下式:8/9 * (10^x-1)=L * p
  根據尤拉定理我們知道:10^Φ(m)≡1(mod m)。 我們要做的就是把根據題目推出來的式子化成尤拉定理的式子(這個具體的推導過程真的沒想出來,參考了大神的部落格才懂:戳這裡) 具體就不贅述了,程式碼描述的還是很清楚的。

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
struct node{
    ll cnt;
    ll p;
};
node num[100];
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
ll Euler(ll n){//尤拉函式
    ll ret=1,i;
    for(i=2;i*i<=n;i++){
        if(n%i==0){
            n/=i;ret*=i-1;
            while(n%i==0){
                n/=i;ret*=i;
            }
        }
    }
    if(n>1)ret*=n-1;
    return ret;
}
ll solve(ll n){//基本算數定理  用num記錄下n由那些素陣列成,這些素數分別有幾個
    int t=0;
    for(ll i=2;i*i<n;i++){
        if(n%i==0){
            num[t].p=i;
            num[t].cnt=0;
            while(n%i==0){
                num[t].cnt++;
                n/=i;
            }
            t++;
        }
    }
    if(n>1){
        num[t].p=n;
        num[t].cnt=1;
        t++;
    }
    return t;//返回素數的種類
}
ll multi(ll a,ll b,ll c) {//由於爆int 所以用的快速乘法和快速冪
    ll ans = 0;
    while (b) {
        if (b & 1) {
            ans += a;ans %= c;
        }
        a += a;a %= c;
        b >>= 1;
    }
    return ans;
}
ll Pow(ll a, ll b, ll c) {
    ll ans = 1;
    while (b) {
        if (b & 1) {
            ans = multi(ans, a, c);
        }
        a = multi(a, a, c);
        b >>= 1;
    }
    return ans;
}

int main(){
    ll L;
    int ca=1;
    while(cin>>L,L){
        ll m=9*L/gcd(L,8);
        if(gcd(10,m)!=1){
            printf("Case %d: 0\n",ca++);
            continue;
        }
        ll pi=Euler(m);
        ll cnt=solve(pi);
        for(int i=0;i<cnt;i++){//縮小pi,找到滿足條件的最小的pi
            for(int j=0;j<num[i].cnt;j++){
                if(Pow(10,pi/num[i].p,m)==1){
                    pi/=num[i].p;
                }
            }
        }
        printf("Case %d: %lld\n",ca++,pi);
    }
    return 0;
}