HDU 4704 [費馬小定理+快速冪] ---狗眼不識多校
Description
Input
2
Output
2Hint 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;
}