简单数学题
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)=∑i=1n(i×∑j=inCij)
求 F(n) mod 1000000007
Input
多组输入,每组输入占一行,包含一个整数n(1 <= n <= 1e18)。
数据不超过300000组。
数据不超过300000组。
Output
对于每组输入,输出一行,包括一个数代表答案。
Sample Input
5
100
100
Sample Output
129
660756544
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)
代码:
//
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
const int mod=;
//
//ll fac[maxn],inv[maxn];
//
//void init()
//{
// fac[0]=fac[1]=1;
// inv[0]=inv[1]=1;
// for(ll i=2;i<maxn;i++)
// {
// fac[i]=fac[i-1]*i%mod;
// inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
// }
// for(ll i=2;i<maxn;i++)
// inv[i]=inv[i-1]*inv[i]%mod;
//}
//ll C(ll x,ll y)
//{
// if(y>x) return 0;
// if(y==0||x==0) return 1;
// return fac[x]*inv[y]%mod*inv[x-y]%mod;
//} ll pow_mod(ll a,ll b){
ll ans=;
while(b){
if(b%==){
ans=ans*a%mod;
}
a=a*a%mod;
b=b/; //这里是转化为二进制之后的进位---左进位
}
return ans;
} //ll a[maxn]; int main()
{
// init();
// for(int i=1;i<=1e3;i++){
//// for(int j=1;j<=i;j++){
//// a[i]=(a[i]+j*C(i,j)%mod)%mod;
//// }
// a[i]=i*pow_mod(2,(i-1))%mod;
// a[i]=(a[i]+a[i-1])%mod;
// //a[i]+=a[i-1];
// }
ll n;
while(~scanf("%lld",&n)){
ll ans=(((n-)%mod)*pow_mod(,n)+)%mod;
cout<<ans<<endl;
}
}