POJ 2478-数论训练D题 费马小定理加快速幂


Description

Input

2

Output

2

        
 



这道题目意思是给出一个数n,求把它分成1份,2份,3份...n份(分出的都是自然数)总共有多少种方法,数据很大结果对1e9+7取余。刚开始看到这题一脸茫然,后经过学习前人的经验,看出了一些端倪,毕竟是与数学有关的题目,不演算是看不出来的。首先列出了n=1到n=6的各种情况,发现满足一个等式:
ans=2^(n-1)mod(1e9+7),
是巧合还是必然?
原来这个问题是高中学概率时接触过的,就是一个隔板的问题,说n个东西,放n-1个隔板是个任取的问题,得C(n-1,n-1),(C这个符号是组合,括号里前者是C的下角标),放n-2个隔板,得C(n-1,n-2)...放一个隔板的话,就是C(n-1,1),将这些组合加起来,就是二项式展开,其中括号里是1+1(因为1的任意次方得1)。因此前面的式子不是偶然。附上二项式定理:
(a+b)^n=(n从0加到n)C(n,k)a^(n-k)*b^k.
知道了算什么之后就是怎么去算了。输入数据很大,只能用字符串输入,由于是求幂的运算,想到了快速幂,正好陈老师给过模版,拿来改成longlong 就可以用。考虑到幂数据很大,所以要用费马小定理来降幂。
 
 
 
上面就是费马小定理,字符串要循环取余,附上取余规则:
(a + b )mod n = (( a  mod  n)+( b  mod  n ))mod  n;
( a – b)mod  n=(( a  mod  n)- (b  mod n)  + n )mod n ;
 ab mod  n=(a mod  n)( b  mod  n)  mod  n;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <string.h>
#define mod 1000000007
using namespace std;
long long int quckpow(long long int m,long long int n,long long int k)
{
    long long int b=1;
    while(n>0)
    {
        if(n&1)b=(b*m)%k;
        n=n>>1;
        m=(m*m)%k;
    }return b;
}

int main()
{

    long long int sum,ans;
    char c[100005];
    while(cin>>c)
    {       sum=0;
        int l=strlen(c);
        for(int i=0;i<l;i++)
            sum=(sum*10+(c[i]-'0'))%(mod-1);
        ans=quckpow(2,sum%(mod-1)-1,mod);
        cout<<ans<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值