题解:AT_arc050_c [ARC050C] LCM 111
arc050c 解题报告
前言
这里提供一种矩阵乘法做法。
问就是因为根本看不懂现有的一篇题解。
思路分析
首先因为 lcm 没什么好的性质,考虑转化为 gcd 求解。
设 表示 个 拼接形成的数。
所以我们实际上要求 。
开始发掘性质了。
性质 1
考虑证明。
钦定 ,根据更相减损术,有:
因为 不是 或 的因数,所以:
同理可以将减法推广:
利用辗转相除法求到边界情况:
证毕。
性质2
当 时, 形如:,其中 周期长度为 ,周期个数为 。
证明显然,不再赘述。
其实打个表也能看出来。
有了这两个性质,这个题就好做了。
设 表示 的周期长度为 ,周期个数为 ,那么 。
然后考虑 的递推。不难发现:
这肯定可以矩阵加速。
设初始矩阵为:
转移矩阵为:
做完了。
总体复杂度为 。有些常数。
代码实现
#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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步