HDU 6467.简单数学题-数学题 (“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛)
简单数学题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 580 Accepted Submission(s): 257
Problem Description
已知
求 F(n) mod 1000000007
F(n)=∑i=1n(i×∑j=inCij)
求 F(n) mod 1000000007
Input
多组输入,每组输入占一行,包含一个整数n(1 <= n <= 1e18)。
数据不超过300000组。
数据不超过300000组。
Output
对于每组输入,输出一行,包括一个数代表答案。
Sample Input
5
100
Sample Output
129
660756544
Source
写的时候,推了好几次,每次都能优化一点点,最后发现就是一个公式。
优化过程代码中注释掉了。
推的过程中用到的一个公式
对于C(n,k)*k求和,k从1到n
n为常量,要求和的式子如下:
1*C(n,1)+2*C(n,2)+3*C(n,3)+.+n*C(n,n)
其中,C(n,k)的意义是组合数,n为下标,k为上标
最终结果为化简后的式子
C(n,k)*k
=k*n!/[(n-k)!k!]
=n*(n-1)!/[(k-1)!(n-k)!]
=n*C(n-1,k-1)
1*C(n,1)+2*C(n,2)+3*C(n,3)+.+n*C(n,n)
=n[C(n-1,0)+C(n-1,1)+C(n-1,2)+.+C(n-1,n-1)]
=n*2^(n-1)
代码:
1 //6467 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 const int maxn=1e5+10; 6 const int mod=1000000007; 7 // 8 //ll fac[maxn],inv[maxn]; 9 // 10 //void init() 11 //{ 12 // fac[0]=fac[1]=1; 13 // inv[0]=inv[1]=1; 14 // for(ll i=2;i<maxn;i++) 15 // { 16 // fac[i]=fac[i-1]*i%mod; 17 // inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; 18 // } 19 // for(ll i=2;i<maxn;i++) 20 // inv[i]=inv[i-1]*inv[i]%mod; 21 //} 22 //ll C(ll x,ll y) 23 //{ 24 // if(y>x) return 0; 25 // if(y==0||x==0) return 1; 26 // return fac[x]*inv[y]%mod*inv[x-y]%mod; 27 //} 28 29 ll pow_mod(ll a,ll b){ 30 ll ans=1; 31 while(b){ 32 if(b%2==1){ 33 ans=ans*a%mod; 34 } 35 a=a*a%mod; 36 b=b/2; //这里是转化为二进制之后的进位---左进位 37 } 38 return ans; 39 } 40 41 //ll a[maxn]; 42 43 int main() 44 { 45 // init(); 46 // for(int i=1;i<=1e3;i++){ 47 //// for(int j=1;j<=i;j++){ 48 //// a[i]=(a[i]+j*C(i,j)%mod)%mod; 49 //// } 50 // a[i]=i*pow_mod(2,(i-1))%mod; 51 // a[i]=(a[i]+a[i-1])%mod; 52 // //a[i]+=a[i-1]; 53 // } 54 ll n; 55 while(~scanf("%lld",&n)){ 56 ll ans=(((n-1)%mod)*pow_mod(2,n)+1)%mod; 57 cout<<ans<<endl; 58 } 59 }