1. 程式人生 > >HDU 4704 Sum(隔板原理+組合數求和公式+費馬小定理+快速冪)

HDU 4704 Sum(隔板原理+組合數求和公式+費馬小定理+快速冪)

ace php 模板 erl char printf 證明 style ron

題目傳送:http://acm.hdu.edu.cn/showproblem.php?pid=4704

Problem Description
技術分享

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. 題意是輸入一個N,求N被分成1個數的結果+被分成2個數的結果+...+被分成N個數的結果,N很大 1.隔板原理 1~N有N個元素,每個元素代表一個1.分成K個數,即在(N-1)個空擋裏放置(K-1)塊隔板
即求組合數C(N-1,0)+C(N-1,1)+...+C(N-1,N-1) 2.組合數求和公式 C(n,0)+C(n,1)+C(n,2)+.+C(n,n)=2^n 證明如下: 利用二項式定理(a+b)^n=C(n,0)a^n+C(n,1)a^(n-1)b+C(n,2)a^(n-2)b^2 +.+C(n,n)b^n
令a=b=1左邊就是2^n 所以題目即求2^(n-1)%(1e9+7) 設MOD為1e9+7 3.費馬小定理(降冪) 因為N很大,所以需要費馬小定理來降冪 費馬小定理是假如a是整數,p是質數,且a,p互質(即兩者只有一個公約數1),那麽a的(p-1)次方除以p的余數恒等於1。 所以可以把(n-1)對(MOD-1)取余 設余數為K 因為2^(MOD-1)%MOD =1
題目即求2^K %MOD 4.快速冪求解 現在K<=MOD,快速冪的復雜度是O(log?N),直接套模板就行
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<string.h>
 5 using namespace std;
 6 
 7 #define MOD 1000000007  
 8 
 9 long long quick_mod(long long a,long long b,long long m)//快速冪,復雜度log2n
10 {
11 long long ans=1; 12 while(b) 13 { 14 if(b&1) 15 { 16 ans=(ans*a)%m; 17 b--; 18 } 19 b/=2; 20 a=a*a%m; 21 } 22 return ans; 23 } 24 25 int main() 26 { 27 28 char str[100010]; 29 long long sum; 30 int len,i; 31 long long M=MOD-1; 32 while(scanf("%s",str)!=EOF) 33 { 34 len=strlen(str); 35 sum=0; 36 for(i=0;i<len;i++) 37 { 38 sum=sum*10+(str[i]-0); 39 sum=sum%M;//費馬小定理 40 } 41 printf("%lld\n",quick_mod(2,(sum-1),MOD));//快速冪 42 } 43 return 0; 44 }

HDU 4704 Sum(隔板原理+組合數求和公式+費馬小定理+快速冪)