您的位置:首页 > 其它

一道坑题,用来更新矩阵模板,WIKI OI 1281

2014-09-30 21:44 260 查看

1281 Xn数列

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

给你6个数,m, a, c, x0, n, g

Xn+1 = ( aXn + c ) mod m,求Xn

m, a, c, x0, n, g<=10^18

输入描述 Input Description

一行六个数 m, a, c, x0, n, g

输出描述 Output Description

输出一个数 Xn mod g

样例输入 Sample Input

11 8 7 1 5 3

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

int64按位相乘可以不要用高精度。

中文题,不解释,主要是数据很吓人,一开始完全没注意溢出的问题,直接跪在了第二个点?然后注意了一些取模细节,跪在了第十个点= = 最后发现乘法都会溢出,改成了俄罗斯农民乘法,以为A了结果发现跪在了第五个点= =,后面才注意到最后乘常数又是直接乘的,所以有数据可以把这种方法搞掉,最后带×的都用俄罗斯农民乘法算,就A了= =。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

long long mod,a,c,x0,n,g;

struct juzhen{

  long long m[2][2];
};

long long modMul(long long a, long long b) {
  long long res = 0LL;
  for (; b; b >>= 1) {
    if (b & 1) res = (res + a) % mod;
    a = (a + a) % mod;
  }
  return res;
}

juzhen mut(juzhen a,juzhen b)
{
  juzhen c;
  for(int i=0;i<2;i++) {
    for(int j=0;j<2;j++) {
      c.m[i][j]=0;
      for(int k=0;k<2;k++) {
	c.m[i][j] += modMul(a.m[i][k], b.m[k][j]);
	c.m[i][j] %= mod;
      }
    }
  }
  return c;
}

juzhen power(juzhen a,long long p)
{
  juzhen ans;
  memset(ans.m,0,sizeof(ans.m));
  for(int i=0;i<2;i++) {
    ans.m[i][i]=1;
  }
  while(p) {
    if(p&1)
      ans=mut(ans,a);
    a=mut(a,a);
    p>>=1;
  }
  return ans;
}

int main()
{
  cin>>mod>>a>>c>>x0>>n>>g;
  juzhen ans;
  a %= mod;
  c %= mod;
  x0 %= mod;
  ans.m[0][0] = a;
  ans.m[0][1] = ans.m[1][1] = 1;
  ans.m[1][0] = 0;
  ans = power(ans,n);

  long long res = (modMul(ans.m[0][0], x0) + modMul(ans.m[0][1], c) ) % mod;
  cout << res % g << endl;
  return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐