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

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值