人,只有自己站起来,这个世界才能属于他。|

园龄:粉丝:关注:

题解:AT_arc050_c [ARC050C] LCM 111

arc050c 解题报告

前言

这里提供一种矩阵乘法做法。

问就是因为根本看不懂现有的一篇题解。

思路分析

首先因为 lcm 没什么好的性质,考虑转化为 gcd 求解。

fi 表示 i1 拼接形成的数。

所以我们实际上要求 fafbgcd(fa,fb)

开始发掘性质了。

性质 1

gcd(fa,fb)=fgcd(a,b)

考虑证明。

钦定 ab,根据更相减损术,有:

gcd(fa,fb)=gcd(fafb,fb)=gcd(10bfab,fb)

因为 fb 不是 25 的因数,所以:

gcd(fa,fb)=gcd(fab,fb)

同理可以将减法推广:

gcd(fa,fb)=gcd(famodb,fb)

利用辗转相除法求到边界情况:

gcd(fa,fb)=gcd(fgcd(a,b),f0)=fgcd(a,b)

证毕。

性质2

ba 时,fafb 形如:1000100010001,其中 0001 周期长度为 b,周期个数为 ab

证明显然,不再赘述。

其实打个表也能看出来。

有了这两个性质,这个题就好做了。

gi,j 表示 0001 的周期长度为 i,周期个数为 j,那么 fafbgcd(fa,fb)=ggcd(a,b),agcd(a,b)g1,b

然后考虑 g 的递推。不难发现:

gi,j=10jgi,j1+1

这肯定可以矩阵加速。

设初始矩阵为:

[gi,jgi,j11]

转移矩阵为:

[10i10000101]

做完了。

总体复杂度为 O(logv)。有些常数。

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std; 
int x,y,mod;
struct node{
	long long h[4][4];
	node(){
		memset(h,0,sizeof(h));
	}
	node operator *(const node &a)const{
		node ans;
		for(int i=1;i<=3;i++){
			for(int j=1;j<=3;j++){
				for(int k=1;k<=3;k++){
					ans.h[i][j]=(ans.h[i][j]+h[i][k]*a.h[k][j]%mod)%mod;
				}
			}
		}
		return ans;
	}
}a,b,c;
node binpow(node a,int b){
	if(b==0) return c;
	node res=binpow(a,b/2);
	if(b&1) return (res*res)*a;
	else return res*res;
}
int qpow(int a,int b){
	if(b==0) return 1;
	int res=qpow(a,b/2);
	if(b&1) return res*res%mod*a%mod;
	else return res*res%mod;
}
int f(int x,int len,int tim){
	if(tim==1) return 1;
	if(tim==2) return qpow(10,len)+1;
	a.h[1][1]=qpow(10,len)+1;
	a.h[1][2]=1;
	a.h[1][3]=1;
	b.h[1][1]=qpow(10,len);
	b.h[1][2]=1;
	b.h[3][1]=1;
	b.h[3][3]=1;
	c.h[1][1]=1;
	c.h[2][2]=1;
	c.h[3][3]=1;
	a=a*binpow(b,tim-2);
	return a.h[1][1];
}
signed main(){
	cin>>x>>y>>mod;
	cout<<f(x,__gcd(x,y),x/__gcd(x,y))*f(y,1,y)%mod<<'\n';
	return 0;
}

后记

祝 CSP2024 rp++

本文作者:Kenma

本文链接:https://www.cnblogs.com/Kenma/p/18689772

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Kenma  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起