[BZOJ 2875 & Vijos 1725] NOI 2012 随机数生成器 · 矩阵乘法+快速乘法

来源:互联网 发布:污水处理厂模拟软件 编辑:程序博客网 时间:2024/05/29 17:21

矩阵乘法+快速乘法

话说这种NOIP的题能出现在NOI里吓谁呢。。。

x0=x

x1=a*x0+c=a*x+c

x2=a*x1+c=a^2*x+a*c+c

x3=a*x2+c=a^3*x+a^2*c+a*c+c

依次类推可以得到:xn=a^n*x+a^(n-1)*c+a^(n-2)*c+.....+a*c+c

一开始我自己写了个矩阵结果挂掉了。。。然后看了一下CCF的题解觉得这个矩阵好巧妙,看来还是需要多加练习啊!

matrix=,我们把xn的式子分成要a^n*x和后面的常数部分,那么我们将matrix自乘n次以后,matrix[1][1]就是a^n,matrxi[1][2]就是后面的常数部分,所以最后的结果就是(x0*matrix[1][1]+matrix[1][2])%m%g。

另外如果直接相乘的话会爆long long,所以要用到一个叫做快速乘法的东西,说白了其实就是个类似快速幂的东西。小学大家都学过,x*y的意义就是y个x相加,剩下的就一目了然啦~(代码line17~24)

#include <stdio.h>#include <iostream>#include <algorithm>#include <string.h>using namespace std;#define ll long long const int n=2;ll a,b,mod,g,k,x0,xn;struct matrix{ll num[3][3];void init(){memset(num,0,sizeof num);}}ans,unit;ll mult(ll x,ll y){ll p=0;for (;y;y>>=1){if (y&1) p=(p+x)%mod;x=(x+x)%mod;}return p;}matrix operator *(matrix a,matrix b){matrix c;c.init();for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)for (int t=1;t<=n;t++)c.num[i][j]=(c.num[i][j]+mult(a.num[i][t],b.num[t][j]))%mod;return c;}int main(){cin>>mod>>a>>b>>x0>>k>>g;unit.num[1][1]=a;unit.num[1][2]=b;unit.num[2][2]=1;ans.num[1][1]=ans.num[2][2]=1;for (;k;k>>=1){if (k&1) ans=ans*unit;unit=unit*unit;}xn=(mult(ans.num[1][1],x0)+ans.num[1][2])%mod;cout<<xn%g<<endl;return 0;}
总结:矩阵里面的所有值并不一定都是我们最终结果想要的,如本题矩阵中的matrix第二行,但是用上这些东西可以帮我们更好的得出最终结果,所以说矩阵乘法写起来虽然简单,但是每一题的矩阵都不尽相同,各有妙处,推出矩阵才是最核心也是最巧妙的。

0 0
原创粉丝点击