1. 程式人生 > 實用技巧 >[HDU-6467]簡單數學題

[HDU-6467]簡單數學題

題目

傳送門

題解

給我們了柿子,我們也只能推柿子咯......

考慮對原式進行如下變換

\[\begin{aligned} F(n) &= \sum_{i=1}^n (i \times \sum_{j=i}^n C_j^i) \\ &= \sum_{j=1}^n\sum_{i=1}^j i\times C_{j}^i \\ &= \sum_{j=1}^n j\times 2^{j-1} \end{aligned} \]

其中,由第二步到第三步使用了組合恆等式,如果不知道可以自行搜尋.

現在這個做法是 \(\mathcal O(Tn)\) 的,對於 \(n\le 10^{18}\)

...我們還需要考慮優化。

注意到 \(\sum\) 內部的 \(2\) 缺少了一個,我們考慮將其補足,有

\[\begin{aligned} 2F(n)&=2\sum_{j=1}^n j\times 2^{j-1} \\ &=\sum_{j=1}^n j\times 2^j \end{aligned} \]

考慮與原式 \(F(n)=\sum_{j=1}^n j\times 2^{j-1}\) 作差,得到

\[\begin{aligned} 2F(n)-F(n) &=\sum_{j=1}^n j\times 2^j-\sum_{j=1}^n j\times 2^{j-1} \\ &=n\times 2^n-\sum_{i=0}^{n-1}2^i \\ &= n\times 2^n-(2^n-1) \\ &= (n-1)\times 2^n+1=F(n) \end{aligned} \]

這就是通項公式了,直接帶 \(n\) 進去算即可。

程式碼

#include<cstdio>

#define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define erep(i,u) for(signed i=tail[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define fi first
#define se second
typedef long long LL;
// typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef unsigned uint;
#define Endl putchar('\n')
// #define int long long
// #define int unsigned
// #define int unsigned long long

#define cg (c=getchar())
template<class T>inline void read(T& x){
    char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T>inline T read(const T sample){
    T x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T>void fwrit(const T x){//just short,int and long long
    if(x<0)return (void)(putchar('-'),fwrit(-x));
    if(x>9)fwrit(x/10);
    putchar(x%10^48);
}
template<class T>inline T Max(const T x,const T y){return x<y?y:x;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
    return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}

const int mod=1000000007;
const int phimod=mod-1;

LL n;

inline int qkpow(int a,LL n){
    n%=phimod;
    int ret=1;
    for(;n>0;n>>=1,a=1ll*a*a%mod)if(n&1)ret=1ll*ret*a%mod;
    return ret;
}

inline int calc(const LL n){
    return ((n-1)%mod*qkpow(2,n)%mod+1)%mod;
}

signed main(){
    while(~scanf("%lld",&n))writc(calc(n),'\n');
    return 0;
}