您的位置:首页 > 其它

【HDU - 4704】Sum 【隔板法+费马小定理降幂】

2017-11-01 16:15 351 查看


分析: 我们可以将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
f22d
;
// 注意这里 k - 1 可能为负数,所以我们要处理下。
printf("%lld\n",power(2ll,(k%mod-1)%mod,mod+1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: