洛谷4714(数论+米勒罗宾)

看到没有矩阵乘法的题解 一开始我是因为被推荐矩阵乘法才来写这一题的
楼下大佬们的数学公式很强 学到了
矩阵乘法是用矩阵优化达到递推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]);//输出
}
posted @ 2018-08-25 09:27  BLUE_EYE  阅读(258)  评论(1编辑  收藏  举报