• [NOI2012]随机数生成器


    这是题目的原始式子(x_{n+1}=(ax_n+c)mod m)

    我们将该式变成矩阵的形式

    (egin{bmatrix}x_{n-1} cend{bmatrix}*egin{bmatrix}a 1\0 1end{bmatrix}=egin{bmatrix}x_{n} cend{bmatrix})

    进行矩阵快速幂(egin{bmatrix}x_{0} cend{bmatrix}*egin{bmatrix}a 1\0 1end{bmatrix}^n)

    然后输出(ans_{1,1}mod g)

    注意:题目中(x_0leq10^{18})需用用到龟速乘

    AC代码

    #include<bits/stdc++.h>
    #define int long long 
    using namespace std;
    const int N=5;
    int x0,A,c,lpw,n,g;
    struct Matrix
    {
    	int m[N][N];
    }a,e;
    void init()
    {
    	memset(a.m,0,sizeof(a.m));
    	memset(e.m,0,sizeof(e.m));
    	a.m[1][1]=x0,a.m[1][2]=c;
        e.m[1][1]=A,e.m[2][1]=e.m[2][2]=1;
    }
    int lowp(int x,int y)
    {
    	int ret=0;
    	while(y)
    	{
    		if(y&1) ret=(ret+x)%lpw;
    		y>>=1;
    		x=(x+x)%lpw;
    	}
    	return ret;
    }
    Matrix mul(Matrix x,Matrix y)
    {
    	Matrix c;
    	memset(c.m,0,sizeof(c.m));
    	for(int i=1;i<=2;++i)
    		for(int j=1;j<=2;++j)
    			for(int k=1;k<=2;++k)	
    				c.m[i][j]=(c.m[i][j]+lowp(x.m[i][k]%lpw,y.m[k][j]%lpw)%lpw)%lpw;
    	return c;
    }
    int ksm(int p)
    {
    	while(p)
    	{
    		if(p&1) a=mul(a,e);
    		e=mul(e,e);
    		p>>=1;
    	}
    }
    signed main()
    {
    	cin>>lpw>>A>>c>>x0>>n>>g;
    	init();
    	ksm(n);
    	cout<<a.m[1][1]%g;		
    	return 0;
    }
    

    上面的是AC的写法,还有一种繁琐一点的写法,但是不知道哪里错了,咕咕咕,有空的时候再来调吧

    /*
    @ author:pyyyyyy
    1.Mulself时忘记把a更新了 
    2.是在是找不出为什么a数组老出错了 
    */
    #include<bits/stdc++.h>
    #define int long long 
    using namespace std;
    int mod,mod1,n,aa,cc,x0;
    int mul(int x,int y)//龟速乘 
    {
    	int ret=0;
    	while(y)
    	{
    		if(y&1) ret=(ret+x)%mod;
    		x=(x+x)%mod;
    		y>>=1;
    	}
    	return ret%mod;
    }
    int f[3],a[3][3];
    int Mul(int f[3],int a[3][3])
    {
    	int c[3];
    	memset(c,0,sizeof(c));
    	for(int i=0;i<2;++i)
    		for(int j=0;j<2;++j)
    			c[i]=(c[i]+mul(f[j],a[j][i]))%mod;
    	memcpy(f,c,sizeof(c));
    }
    int Mulself(int a[3][3])
    {
    	int c[3][3];
    	memset(c,0,sizeof(c));
    	for(int i=0;i<2;++i)
    		for(int j=0;j<2;++j)
    			for(int k=0;k<2;++k)
    				c[i][j]=(c[i][j]+mul(a[i][k],a[k][j]))%mod;
    	memcpy(a,c,sizeof(c));
    }
    int Mulother(int w[3][3],int b[3][3])
    {
    	int c[3][3];
    	memset(c,0,sizeof(c));
    	for(int i=0;i<2;++i)
    		for(int j=0;j<2;++j)
    			for(int k=0;k<2;++k)
    				c[i][j]=(c[i][j]+mul(w[i][k],b[k][j]))%mod;
    	memcpy(w,c,sizeof(c));
    }
    void ksm(int x)
    {
    	int w[3][3];
    	for(int i=0;i<2;++i)
    		w[i][i]=1;
    	while(x)
    	{
    		if(x&1) Mulother(w,a);
    		Mulself(a);
    		x>>=1;
    	}
    	memcpy(a,w,sizeof(w));
    }
    signed main()
    {
    	cin>>mod>>aa>>cc>>x0>>n>>mod1;	
    	a[0][0]=aa,a[0][1]=1,a[1][0]=0,a[1][1]=1;
    	f[0]=x0,f[1]=cc;
    
    	ksm(n);
    	for(int i=0;i<2;++i)
    	{
    		for(int j=0;j<2;++j)
    			cout<<a[i][j]<<' ';
    		cout<<'
    ';
    	}
    	Mul(f,a); 
    	for(int i=0;i<2;++i) cout<<f[i]<<' ';
    	cout<<endl;
    	cout<<a[0][1]%mod1;
    	return 0;
    }
    
  • 相关阅读:
    2018-div-matrix
    cf663div2
    生成树
    Call to your teacher
    并查集总结
    分组背包
    被3整除的子序列
    多重背包
    12.05
    django生命周期图
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/12718662.html
Copyright © 2020-2023  润新知