FZU_1017 Playing with Calculator

http://acm.fzu.edu.cn/problem.php?pid=1017

題意:

給你一個K,要你求一個n, k使得k個n組成的數正好能被K整除,要求首先考慮最小的n,然後考慮最短的k。

思路:

這個題和HDU_2462相似。首先我們可以這樣考慮,對於一個由k個n組成的數字,我們不能直接去枚舉n和k,那樣顯然會超時(因爲有可能存在不存在n和k的情況),這樣我們就設法去把這樣的n,k表示成另外一種形式,這樣是一定能表示的,因爲n,k就可以唯一確定一個數,nn...nn = (99..99) / 9 * n = (10^k - 1) /9*n ,化簡到這裏我們就可以直接求了,下面就是過程的推導:
(10^k - 1 ) / 9 * n = 0( mod K )  ---->   (10^k - 1)*n = 0(  mod (9*K) )  ,爲了設法將n從左邊除掉,我們可以這樣化簡 ------->

(10^k - 1) = 0 ( mod ( 9*K/gcd(9*K , n) ) ) , 依據是 ac = bc( mod p ) 化簡成a = b ( mod p ) 的條件是 gcd( c , p ) = 0。

到了這裏之後,基本的思路就出來了,我們另 p = 9 * K /  gcd( 9*K , n ) , 上式就變成了:(10^k - 1) = 0 ( mod p ) ---->10^k = 1( mod p )

到這裏之後,學過歐拉定理的同學一定就可以看出來了,a^phi(p) = 1 ( mod p ) 當gcd(a, p) = 1 時成立。 這樣我們就可以先判斷gcd(10 , p )是否等於1 ,如果gcd(10 , p) != 1  ,那麼方程一定無解;否則phi(p) 一定是方程的一個解,但是並不一定是最小的解,所以我們還要將p分解質因數然後再判斷每個約數是否滿足條件即可。

還有一個沒有證明的問題就是10^k = 1 ( mod p )當gcd(10 , p)!=1時無解,這個結論可以這樣來證明:我們令x = 10 ^ (k-1) , 則上式就可以變成:10*x = 1 ( mod p ),如果解出了x,那麼k也就解出來了,上述那個方程有解的條件就是 gcd(10 , p ) == 1 , 所以得證。 

代碼:

#include <stdio.h>
#include <string.h>

typedef long long LL ;
int K ;
const int PP = 110  ;
int prime[PP] , cnt ;
bool is_p[PP] ;
int fac[20] , num[20] , fnum ;
int ans , p ;

void make_prime(){
    for(int i=1;i<PP;i++)   is_p[i] = 1 ;
    cnt = 0 ;
    for(int i=2;i<PP;i++){
        if( is_p[i] ){
            prime[ cnt++ ] = i ;
            for(int j=2;j*i<PP;j++) is_p[i*j] = 0 ;
        }
    }
}
int gcd(int a, int b){
    while( b ){
        int c = a ;
        a = b ;
        b = c % b ;
    }
    return a ;
}
void get_fac(int n){
    fnum = 0 ;
    for(int i=0;i<cnt && prime[i]*prime[i]<=n;i++){
        if( n%prime[i] == 0 ){
            int c = 0 ;
            while( n%prime[i] == 0){
                c ++ ; n/=prime[i] ;
            }
            fac[ fnum ] = prime[i] ; num[ fnum++ ] = c ;
        }
    }
    if( n > 1 ) fac[ fnum ] = n , num[ fnum++ ] = 1 ;
}

int pmod(int a, int b, int p){
    int res = 1 % p , add = a % p  ;
    while( b ){
        if( b&1 )   res = res * add % p ;
        add = add * add % p ;
        b >>= 1 ;
    }
    return res ;
}

void dfs(int pos , int res ){
    if( pos == fnum ){
        if( pmod(10 , res , p) == 1 ) {
            ans = ans < res ? ans : res  ;
        }
        return ;
    }
    dfs( pos+1 , res)  ;
    int rr = res ;
    for(int i=1;i<=num[ pos ] ;i++){
        rr = rr * fac[ pos ] ;
        dfs(pos+1 , rr) ;
    }
}
int get_phi(int n){
    int res = n ;
    for(int i=0;i<cnt && prime[i]*prime[i]<=n ;i++){
        if( n%prime[i] == 0 ){
            res = res / prime[i] * ( prime[i] - 1 ) ;
            while( n%prime[i] == 0 )    n /= prime[i] ;
        }
    }
    if( n > 1 ) res = res / n * (n - 1) ;
    return res ;
}

int check( int n ){
    p = 9 * K / gcd( 9*K , n ) ;
  //  p = K / gcd(9*K ,  n) * 9 ;
    if( gcd(10,  p) != 1)   return -1 ;
    int ph = get_phi( p ) ;
    get_fac( ph ) ;
    ans = ph  ;
    dfs(0 , 1) ;
    return ans ;
}

int main(){
    make_prime() ;
    while( scanf("%d",&K) == 1 ){
        bool ok = 0 ;
        for(int i=1;i<=9;i++){
            int res = check( i ) ;
            if( res == -1 ) continue ;
            ok = 1 ;
            printf("%d %d\n",i , res);    break ;
        }
        if( !ok )   printf("-1\n");
    }
    return 0 ;
}


發佈了211 篇原創文章 · 獲贊 24 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章