1. 程式人生 > >4704】Sum 【隔板法+費馬小定理降冪】

4704】Sum 【隔板法+費馬小定理降冪】

這裡寫圖片描述
分析: 我們可以將n劃分為n 個1,然後我們分1就行了。 s(k) 為 從n-1個空中插入k-1個隔板,即C(n-1,k-1),現在要求C(n-1,0)+C(n-1,1)+C(n-1,2)…+C(n-1,n-1) ,由二項式定理公式 C(n,0)+C(n,1)+C(n,2)…C(n,n)= 2^n. 可知我們要求的是2^(n-1)
但是題目中的N太大了,無法計算,所有我們可以用費馬小定理降冪,
費馬小定理為 a^( p - 1) = 1 ( mod p ) 其中p為素數,同時gcd(a,p)==1。
所以 可以有降冪公式 a ^ n % p= a ^ ( n % ( p-1 ) ) %p ,因為不管多少個a^(p-1) 在p的模下都會是1,所以我們找到餘數就行了。同時為了防止(n%(p-1))可能為負數 , 我們可以用 (n%(p-1)+p-1)%(p-1) 來找到最小的正整數餘數。
將n降冪到mod級數,之後我們用快速冪就行了。

補充: 因為費馬小定理是尤拉定理的特殊形式。
尤拉定理 a ^ phi (p) = 1 ( mod p ) ,其中gcd(a,p)==1 即可 。
同樣可以轉化為降冪形式 假如想求 a ^n % mod , 只要gcd(a,mod)==1,那麼我們都可以轉化 a ^ (n % phi(mod)) % mod如果n%phi(mod)也會出現負數的情況,處理方法同費馬小定理的時候。假如mod為素數 , phi(mod)=mod-1,帶入不就是費馬小定理降冪了, 所以啊,都是尤拉定理的特殊形式。
程式碼

#include<bits/stdc++.h>
using namespace std;
typedef pair<int
,int>pii; #define first fi #define second se #define LL long long #define fread() freopen("in.txt","r",stdin) #define fwrite() freopen("out.txt","w",stdout) #define CLOSE() ios_base::sync_with_stdio(false) const int MAXN = 1e5; const int MAXM = 1e6; const int mod = 1e9+7 -1 ; // p - 1 const int inf = 0x3f3f3f3f
; LL power(LL a,LL b,LL c){ LL s=1,base=a%c; while(b){ if(1&b) s=s*base%c; base=base*base%c; b>>=1; } return s; } char s[MAXN]; int main(){ CLOSE(); // fread(); // fwrite(); while(scanf("%s",s)!=EOF){ LL k=0; for(int i=0;s[i];i++) k=(k*10+s[i]-'0')%mod; // 注意這裡 k - 1 可能為負數,所以我們要處理下。 printf("%lld\n",power(2ll,(k%mod-1)%mod,mod+1)); } return 0; }