【HDU - 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值