目錄題目傳送門1
題目傳送門2
題目傳送門3
計算\(\sum_^i^m*m^i\)
\(\%\)
\(10^9+7\)
\((1 \leq n \leq 10^9)\)
bzoj3157:\(1 \leq m \leq 200\)
bzoj3516:\(1 \leq m \leq 1000\)
bzoj4126:\(1 \leq m \leq 50000\)
一般題目短的都很毒這道題各種做法都有,想不想的出來似乎只有看推式子的能力了。推不出式子的話那就只能亂搞了。先講一種自己單獨想出來的但是複雜度**的做法,複雜度似乎是\(o(m^3log(n))\)的,然而似乎可以過。。首先我們把這個式子用拆成這樣:\(\sum_^i^m*m^i=m*(1^m+m(2^m+m(...m(n^m))))\),然後可以發現這個式子是非常有規律的,於是我們就考慮矩乘,但這個\(i^m\)非常的難弄,所以我們在矩陣中同時記錄這個\(i^m\),然後一起轉移就行了,然而這個看起來非常好寫的做法複雜度很高,然而**也調了好久(感覺自己蒿菜啊~),所以**就不放了2333。
然後開始講一下比較高階的做法。。首先是\(o(m^2log(n))\)的做法,我們記\(f(n,k)=\sum_^i^k*m^i\),那麼:
\[\begin
& f(n+1,k) &= \sum_^i^k*m^i \\
&=\sum_^i^k*m^i+m \\
&=\sum_^(i+1)^k*m^+m \\
&=\sum_^m^\sum_^kc_k^j*i^j+m \\
&=\sum_^c_k^j*m\sum_^ni^j*m^i+m \\
&=\sum_^kc_k^j*m*f(n,j)+m
\end
\]這樣我們就可以用\(o(m^2)\)的時間從\(n\)轉移到\(n+1\)。我們繼續:
\[\begin
& f(2n,k) &= \sum_^i^k*m^i \\
&= \sum_^i^k*m^i+\sum_^i^k*m^i \\
&= f(n,k)+\sum_^(i+n)^k*m^ \\
&= f(n,k)+\sum_^m^\sum_^c_k^j*i^j*n^ \\
&= f(n,k)+\sum_^c_k^j*n^*m^n\sum_^i^j*m^i \\
&= f(n,k)+m^n\sum_^c_k^j*n^*f(n,j)
\end
\]這樣我們就可以同樣用\(o(m^2)\)的時間從\(n\)轉移到\(2n\)。接下來就是比較簡單的遞迴處理了,總複雜度為\(o(m^2log(n))\)。
#include using namespace std;
typedef long long ll;
bool finish_read;
templateinline void read(t &x)while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;finish_read=1;}
templateinline void print(t x)
templateinline void writeln(t x)
templateinline void write(t x)
/****************=header template**********====*/
#define pause printf("press enter key to continue..."); fgetc(stdin);
const int md=1e9+7;
const int n=205;
ll n;
int m;
ll c[n][n],f[n][n];
/****************===define area***************=*/
ll powe(ll x,ll y)
return res;
}void init() }}
void calc(ll x,int y)
return ;
} if(x&1)
(f[y][i]*=m)%=md;(f[y][i]+=m)%=md;
} }else
(f[y][i]*=pw)%=md;
(f[y][i]+=f[y+1][i])%=md;
} }}int main()
然而這麼高階的做法過不去bzoj3516,畢竟老年機於是我們思考更加優越的做法,我們發現上面乙個做法實際上可以用一維記錄,因為\(n\)只能轉移到\(n+1\)或者\(2n\),這樣我們就需要思考是否可以省去\(n\)這一維。於是我們記\(f(k)=\sum_^ni^k+m^i\)
那麼:\[\begin
& (m-1)*f(k) &= (m-1)*\sum_^i^k*m^i \\
&= \sum_^ni^k*m^ -\sum_^ni^k*m^i \\
&= \sum_^(i-1)^k*m^i-\sum_^ni^k*m^i \\
&= \sum_^((i-1)^k-i^k)*m^i+n^km^ \\
&= \sum_^m^i\sum_^c_k^j*(-1)^*i^j+n^km^ \\
&= \sum_^c_k^j*(-1)^*\sum_^i^j*m^i+n^km^ \\
&= \sum_^c_k^j*(-1)^*f(j)+n^km^
\end
\]於是我們可以得出\(f(k)=\frac^c_k^j*(-1)^*f(j)+n^km^}\)。這樣我們就得到了\(o(m^2)\)的做法,就可以過bzoj3516的資料範圍了。
#include using namespace std;
typedef long long ll;
bool finish_read;
templateinline void read(t &x)while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;finish_read=1;}
templateinline void print(t x)
templateinline void writeln(t x)
templateinline void write(t x)
/****************=header template**********====*/
#define pause printf("press enter key to continue..."); fgetc(stdin);
const ll md=1e9+7;
const int n=2005;
int n,m;
ll c[n][n],f[n];
/****************===define area***************=*/
void init() }}
ll powe(ll x,int y)
return res;
}int main() {
read(n);read(m);
init();
if(m==1) return printf("%lld\n",((ll)(n+1)*n/2)%md),0;
ll sum=powe(m,n+1);
f[0]=(sum-m+md)%md;
ll div=powe(m-1,md-2);f[0]*=div;f[0]%=md;
for(int i=1;i<=m;i++) {
sum*=n;sum%=md;f[i]=sum;
for(int j=0;j然後。。\(o(m)\)的高階演算法。。留個坑,奶一口肯定能夠填回來。
BZOJ1052 BZOJ3760 覆蓋問題
原題位址 先說自己的逗比方法 二分答案,把所有點用乙個最小的矩形 框 起來,易證矩形的其中乙個端點是最優解中正方形的乙個端點,然後列舉四個端點後遞迴處理,差不多了 然後 olz黃學長的o n 做法 ac code include include include using namespace std...
動態點分治 bzoj 3730,bzoj 1095
總結一下動態點分治的模板。對於乙個樹,把它點分的同時記錄每個點的所有父親 logn個 並記錄點距其父親的距離。具體實現就是dfs的時候fa x dep x u,dis x dep x d bzoj1095 您需要寫乙個程式支援反轉點的顏色,求距離最遠的黑色點對的距離。解析 在每個點u存乙個堆st記錄...
福慧雙修 探險 BZOJ4398 BZOJ2407
分析 雙倍經驗 資料範圍不同 我們考慮,我們必定是從1走一條邊到節點i,之後從i到j跑最短路,之後再從j到1走另一條邊的情況下,不會重複,並且是答案。那麼我們考慮預處理出pre i 表示從1走到i滿足最短路的並且經過pre i pre i 為路徑第二個節點。那麼,針對每乙個邊,x,y,z,v 滿足當...