隨 rand dp,原根,矩陣 倍增優化

2022-04-14 05:27:17 字數 2343 閱讀 8760

題幹:對於$10\%$的資料mod=2,a[i]必定為1,直接輸出1.

對於另$10\%$的資料n=1,輸出$ a[1]^m\%mod $ 注意模mod而非$1e9+7$。

對於$50\%$的資料,我們考慮dp,

設$ f[i][j] $為i次操作後結果為j的方案數,

易得轉移方程為:$ f[i][j*a[k]\%mod]=\sum\limits f[i-1][j] $(考場上想到的sb dp)

但$ o(n*m*mod) $的複雜度令人望而卻步,並不能多得分。

於是考慮優化,觀察得$mod<=300$而$n<=100000$,想到類似離散化的思路,

用乙個陣列$c[i]$記錄第$i$數出現的次數

轉移方程式變為:$ f[i][j*a[k]\%mod]=\sum\limits f[i-1][j]*c[k] $

時間複雜度變為$ o(m*mod^2) $,期望得分50pts。

對於$ 100\% $的資料,我們考慮優化,

方法一:矩陣快速冪+原根優化(然而蒟蒻並不會)附上wd大神部落格

方法二:倍增優化,

回過頭來再看剛才的dp式子,我們可得:$ f[i+q][j*a[k]\%mod]=f[i][j]*f[q][k] $

同樣可得:$ f[2*i][j*k\%mod]=f[i][j]*f[i][k] $

於是我們可以在$ o(logm) $的時間求出 $f[2^1],f[2^2],f[2^3]\cdots,f[2^n]  (2^n<= m< 2^) $

所以我們可以使用快速冪的思想,將m二進位制拆分,下附普通快速冪模板:

ll qpow(ll x,ll y,ll mod)

return ans;

}

將其中y變為m,x變為f陣列,ans為g陣列。

$f[i][j]$陣列含義也變為操作$2^i$次,結果為$j$的方案數。

而$g[i][j]$陣列為操作$2^1+2^2+2^3+\cdots+2^i$次,結果為$j$的方案數。

所以$ f[i][j*k\%mod]=\sum\limits_^\sum\limits_^f[i-1][j]*f[i-1][k] $

$ g[i][j*k\%mod]=\sum\limits_^\sum\limits_^g[i-1][j]*f[i][k] $

還有最後乙個問題:記憶體

當前我們的空間複雜度為:$ o(logm*mod) $,而f,g陣列都只與上乙個狀態有關,顯然可用滾動陣列,最後的空間複雜度為$o(2*mod)$,時間複雜度為$o(mod^2logm)$。

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;

7#define r register

8#define ll long long

9inline ll read()

13while(cc>='

0'&&cc<='9'

)14

15return aa*bb;16}

17const

int p=1e9+7;18

const

int n=1005;19

ll qpow(ll x,ll y,ll mod)

2026

return

ans;27}

28 ll n,mod,m,tmp=0,cur=0

;29 ll ans,f[2][n],g[2

][n];

30 inline void split(int

y)31

40 y>>=1

;41 memset(f[tmp^1],0,sizeof

(f[tmp]));

42for(r int i=1;ii)

46 tmp^=1;47

}48}49

intmain()

5053

if(n==1)59

for(r int i=1;i<=n;++i)

60 ++f[0

][read()];

61 g[0][1]=1;62

split(m);

63for(r int i=1;i<=mod;++i)

64 ans=(ans+g[cur][i]*i%p)%p;

65 ans=1ll*ans*qpow(n,m*(p-2),p)%p;

66 printf("

%lld\n

",ans);

67return0;

68 }

然後我們就開心的ac了

原根 51nod 1135(原根)

設m是正整數,a是整數,若a模m的階等於 m 則稱a為模m的乙個原根。其中 m 表示m的尤拉函式 給出1個質數p,找出p最小的原根。input 輸入1個質數p 3 p 10 9 output 輸出p最小的原根。sample input 3sample output 2題意 求乙個質數的最小原根 分析...

1135 原根(概念)

設m是正整數,a是整數,若a模m的階等於 m 則稱a為模m的乙個原根。其中 m 表示m的尤拉函式 給出1個質數p,找出p最小的原根。輸入輸入1個質數p 3 p 10 9 輸出輸出p最小的原根。輸入樣例 3輸出樣例 2a是p的原根滿足 p 1的所有質因子p1,p2,pk,都滿足a p 1 pi p 1...

階 原根 指標

定義 設 使得 成立的最小的 稱為對模 的階,記為 定理 如果模 有原根,那麼它一共有 個原根。定理 若,則。定理 如果 為素數,那麼素數 一定存在原根,並且模 的原根的個數為 定理 設 是正整數,是整數,若 模的階等於 則稱為模 的乙個原根。假設乙個數 對於模來說是原根,那麼 的結果兩兩不同,且有...