HDU 4704 Sum

HDU 4704 Sum :http://acm.hdu.edu.cn/showproblem.php?pid=4704

题目描述: 

Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2067    Accepted Submission(s): 861


Problem Description
HDU 4704 Sum_第1张图片
 

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.
 

Source
2013 Multi-University Training Contest 10
 

题目大意:

S(k)表示把N分成k个整数和的分法数,此题要求解的是(S(1)+S(2)+...+S(N))mod(10^9+7)的值。

题目分析:

根据隔板定理,把N分成一份的分法数为C(1,n-1), 

把N分成两份的分法数为C(2,n-1),

把N分成三份的分法数为C(3,n-1),.... ,

把N分成N份的分法数为C(n-1,n-1)。

设sum=S(1)+S(2)+...+S(N),根据组合数求和公式,sum=2^(n-1)。所以,原式可化为(2^(N-1))mod(10^9+7)

由于N的值比较大,第一步想到的就是要用字符数组来对其进行处理,且由于N比较大,且2和MOD互素,所以要借助于费马小定理求解,2^(MOD-1)modMOD==1,即要看(N-1)中有有多少个(MOD-1),则(N-1)%(MOD-1)的值再对MOD进行快速幂求解即可。


代码实现:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

long long quick_mod(long long a,long long b,long m)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a)%m;
            b--;
        }
        b/=2;
        a=a*a%m;
    }
    return ans;
}

const long long MOD=1000000000+7;
int main()
{
    char str[100010];
    long long sum;
    long long M=MOD-1;
    while(scanf("%s",str)!=EOF)
    {
        int len=strlen(str);
        sum=0;
        for(int i=0;i<len;i++)
        {
            sum=sum*10+(str[i]-'0');
            sum=sum%M;
        }
        //cout<<"sum="<<sum<<endl;
        printf("%lld\n",quick_mod(2,(sum-1),MOD));
    }
    return 0;
}



你可能感兴趣的:(快速幂,费马小定理,组合数求和公式,隔板定理)