zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/12718662.html
Copyright © 2011-2022 走看看