dreamoon的十进制矩阵快速幂以及+1循环节降幂记录

链接:https://ac.nowcoder.com/acm/contest/885/B
来源:牛客网
 

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

You are given four positive integers x0,x1,a,bx_0, x_1, a, bx0​,x1​,a,b. And you know xi=a⋅xi−1+b⋅xi−2x_i = a \cdot x_{i-1} + b \cdot x_{i-2}xi​=a⋅xi−1​+b⋅xi−2​ for all i≥2i \ge 2i≥2.

Given two positive integers n, and MOD, please calculate xnx_nxn​ modulo MOD.

Does the problem look simple? Surprise! The value of n may have many many digits!

输入描述:

The input contains two lines.
The first line contains four integers x0,x1,a,bx_0, x_1, a, bx0​,x1​,a,b (1≤x0,x1,a,b≤1091 \le x_0, x_1, a, b \le 10^91≤x0​,x1​,a,b≤109).
The second line contains two integers n, MOD (1≤n<10(106),109<MOD≤2×1091 \le n < 10^{(10^6)}, 10^9 < MOD \le 2 \times 10^91≤n<10(106),109<MOD≤2×109, n has no leading zero).

输出描述:

Print one integer representing the answer.

示例1

输入

复制

1 1 1 1
10 1000000001

输出

复制

89

说明

The resulting sequence x is Fibonacci sequence. The 11-th item is 89.

示例2

输入

复制

1315 521 20185 5452831
9999999999999999999999999999999999999 1000000007

输出

复制

914730061

十进制优化的矩阵快速幂(跑的不是很快,还能优化)

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N=1e6+5;
struct mat{
	ll m[2][2];
	void print(){
		for(int i=0;i<2;i++){
			for(int j=0;j<2;j++){
				printf("%lld ",m[i][j]);
			}
			printf("\n");
		}
		printf("\n");
	}
};
ll mod;
mat operator*(mat a,mat b){
	mat s;
	memset(s.m,0,sizeof(s.m));
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			for(int k=0;k<2;k++){
				s.m[i][j]=(s.m[i][j]+a.m[i][k]*b.m[k][j]%mod)%mod;
			} 
		}
	}
	return s;
}
char n[N];
int main(){
    ll x0,x1,a,b;
    scanf("%lld%lld%lld%lld",&x0,&x1,&a,&b);
    scanf("%s",n+1);
    scanf("%lld",&mod);
    int len=strlen(n+1);
	mat ans={1,0,0,1};
	mat A={a,b,1,0};
	for(int i=len;i>=1;i--){
		int up=n[i]-'0';
		mat B=A;
		if(up){
			for(int i=1;i<up;i++) A=A*B;
		    ans=ans*A;
			for(int i=up;i<10;i++) A=A*B;
		}
		else{
			for(int i=1;i<10;i++) A=A*B;
		}
	}
	printf("%lld\n",((ans.m[1][0]*x1%mod)+(ans.m[1][1]*x0%mod))%mod);
	return 0;
}



 

WJYTXWD的神仙降幂公式,拿个小本本记好,虽然不知道为啥

ll solve(ll x){
    ll ans1=1,ans2=1,xx=x;
    for(int i=0;i<pn;i++){
        if(1ll*pri[i]*pri[i]>x) break;
        if(x%pri[i]==0){
            ans1*=(pri[i]-1)*(pri[i]+1);
            ans2*=pri[i];
            while(x%pri[i]==0) x/=pri[i];
        }
    }
    if(x>1){
        ans1*=(x-1)*(x+1);
        ans2*=x;
    }
    return xx/ans2*ans1;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值