HDU6467 簡單數學題
阿新 • • 發佈:2020-09-07
HDU6467 簡單數學題
思路:
簡單變換,先推式子
\[F(n) = \sum_{i=1}^n (i \times \sum_{j=i}^n C_j^i)\\ = \sum_{i=1}^n i \times \sum_{j=i}^n{j \choose i}\\ =\sum_{j=1}^n\sum_{i=1}^j i \times C_j^i\\ =\sum_{j=1}^nj2^{j-1}\\ =\frac{\sum_{j=1}^nj2^j}{2}\\ 至此,便得到了O(Tn)的演算法,顯然過不了\\ 發現無法從式子入手,可考慮數列分治\\ 轉換為已知F(n)求F(2n)\\ 易得,F(2n)=(F(n)+n\sum_{i=1}^n2^n)2^n,累和轉換為等比數列求和\\ 時間複雜度為O(Tlog^2n),依然過不了\\ 考慮將數列分治與快速冪合併,時間複雜度O(Tlogn),詳見程式碼 \]
#include<map> #include<cmath> #include<stack> #include<deque> #include<queue> #include<cstdio> #include<vector> #include<climits> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; # define Type template<typename T> # define ll long long # define read read1<ll>() Type T read1(){ T t=0;char k; bool v=0; do (k=getchar())=='-'&&(v=1);while('0'>k||k>'9'); while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar(); return v?-t:t; } ll qkpow(ll n,ll x,ll mo){ if(!x)return 1; ll t=qkpow(n,x>>1,mo); t=t*t%mo; if(x&1)t=t*n%mo; return t; } # define mod 1000000007ll # define I 500000004ll ll q2(ll x){return qkpow(2,x,mod);} ll w; ll get(ll x){ if(x==1){w=2;return 2;} ll mid=x>>1,v=get(mid),tl=(w*2+mod-2)%mod; v=(v+(v+mid%mod*tl)%mod*w)%mod; w=w*w%mod; if(x&1)w=w*2%mod,v=(v+x%mod*w)%mod; return (v+mod)%mod; } int main(){ ll n; while(~scanf("%lld",&n)) printf("%lld\n",get(n)*I%mod); return 0; }