1. 程式人生 > >HDU 4704 [費馬小定理+快速冪] ---狗眼不識多校

HDU 4704 [費馬小定理+快速冪] ---狗眼不識多校

Description

Input

2

Output

2

        
 
Hint 1. For N = 2, S(1) = S(2) = 1. 2. The input file consists of multiple test cases.

Sample Input

2

Sample Output

2

        
 

Hint

1. For N = 2, S(1) = S(2) = 1. 2. The input file consists of multiple test cases.

PS:據說是2013的多校第9場的題,簡直燒腦子,至今寫這篇題解仍舊沒有繞過來一個點,過陣子再回來看看吧;

題目大意:給你一個N , 求S(1)+ S(2) +...+S(n) 的組合數 , 其中S(K)代表可以把N拆分為K個數字 的情況數。 特別繞腦子;

舉例分析:

1.當N=1 ,  S(1)  = 1 , 因為N=1可以拆成1這一個數字   , 所以答案是  1 

2.當N=2 . S(1) = 1 ,因為N=2,拆成1個數字,還是2 ,一種情況;  S(2) 是代表可以拆分為2個數字, 那邊是 1 和 1  一種情況, 所以答案是  2

3.當N=3,S(1) = 1 ;  S(2) = (1+2) || (2+1) ; S(3) = 3 ;   所以答案是  1 + 2 + 1 = 4 ;

4.當N=4, S(1) = 1 ; S(2) = (2+2)||(1+3)||(3+1) ; s(3) = (1+1+2)||(1+2+1)||(2+1+1) ; S(4) = 4 ; 所以答案是 1+3+3+1 = 8 ;

推規律發現 , find的答案就是  2^(n-1) ; 但是題中的N特別大, 所以就得考慮如何去化簡這個n;

這裡首先知道 a^b%mod 可以用快速冪解決, 那麼 a^n%mod , 且題中mod是一個質數, 所以可以用費馬小定理去解決;

費馬小定理:a^(p-1)%p = 1 (這裡的p就是mod,且p是一個質數)

化簡:   a^n%p =  a^(n%(p-1))%p     所以答案就是求 n % (p-1) , 隨後字串讀入然後不斷對新生成的n % p-1 即可 ;

對如上進行推導: 首先對於一個整數n可以做如此拆分: n = k(p-1)+n%(p-1) 其中k為係數,p為去摸數

那麼對於本題 a^n%p = a^(k(p-1)+n%(p-1))%p ----> a^(k*(p-1))%p * a^(n%(p-1))%p , 前者就是費馬小定理,答案為1,係數k不影響

所以推出 化簡所事;

本題告一段落QAQ

AC程式碼:

#include <iostream>
#include <cstdio>
#define ll long long 
#define mod 1000000007
using namespace std;
ll quick(ll a , ll b)
{
    ll res = 1 ;
    a = a % mod ;
    while(b)
    {
        if(b&1)  res = res * a %mod ;
        b>>=1;
        a = a * a %mod ;
    }
    return res ; 
}
int main()
{
    char s[500000] ;
    while(scanf("%s",s)!=EOF)
    {
        ll n = 0 ; 
        for(int i = 0 ; s[i] ; i++)
            n = n*10 + (s[i]-'0') , n%=mod-1;
        if(!n) printf("1\n");
        else cout<<quick(2,n-1)<<endl; 
    }
    return 0;
}