洛谷4714(數論+米勒羅賓)
阿新 • • 發佈:2018-08-25
log names cpp 代碼 anti class turn operator per
看到沒有矩陣乘法的題解 一開始我是因為被推薦矩陣乘法才來寫這一題的
樓下大佬們的數學公式很強 學到了
矩陣乘法是用矩陣優化達到遞推logN解法的一種算法(大佬們無視)
可以用矩陣做的題推薦一道 https://nanti.jisuanke.com/t/16442
遞推式是 設a()表示已經越獄的 b()表示沒有越獄的
則 a(i)=a(i-1)m+b(i-1);表示已經越獄的最後一個人是什麽都可以 沒越獄的只能和倒數第二個一樣
b(i)=(a(i-1)+b(i-1))m-a(i)=(m-1)*b(i-1);有m^n種可能 相減即可
b(1)=m;
下面貼代碼
#include<iostream> #include<cstdio> using namespace std; typedef long long ll;//不打long long 會WA const ll MOD=100003; ll i,j,n,m; struct node{ ll s[2][2]; node(){ for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) s[i][j]=0; }//矩陣初始為0; node operator * (const node& b){ node all; for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) for(int k=0;k<=1;k++){ all.s[i][j]+=s[i][k]*b.s[k][j];//矩陣乘法 不知道戳百科 (行的每個元素*列的每個元素) all.s[i][j]%=MOD;//不能忘了取模 } return all;//return矩陣 } }a,b,ans; node qpow(node t,ll k){ node w;w.s[0][0]=0;w.s[0][1]=m;//快速冪 for(ll i=k;i;i>>=1,t=t*t) if(i&1)w=w*t;return w; } int main(){ scanf("%lld%lld",&m,&n); a.s[0][0]=m;a.s[0][1]=0;// a.s[1][0]=1;a.s[1][1]=m-1;//矩陣的初始化 ans=qpow(a,n-1); printf("%lld",ans.s[0][0]);//輸出 }
洛谷4714(數論+米勒羅賓)