题解:AT_arc050_c [ARC050C] LCM 111

题解:求a个1与b个1组成数的LCM余数

一道比较简单的题。(我绝对不会告诉你这题我改了很久)

题目意思很简单,我就不过多解释了,我们直接进入正题。

题目要我们求 aaa111 组成的数与 bbb111 组成的数的最小公倍数除以 mmm 后的余数。先不考虑多的,我们先设定一个函数 change⁡(x)\operatorname{change}(x)change(x) 表示由 xxx111 组成的数,也就是这个:

change⁡(x)=111111...11⏟x个1\operatorname{change}(x)=\underbrace{111111...11}_{x\text{个}1}change(x)=x1111111...11

写的更加数学化一点就是:

change⁡(x)=10x−19\operatorname{change}(x)=\frac{10^x-1}{9}change(x)=910x1

那么我们要求的答案就是:

lcm⁡(change⁡(a),change⁡(b)) mod m\operatorname{lcm}(\operatorname{change}(a),\operatorname{change}(b))\bmod mlcm(change(a),change(b))modm

同时又有 lcm⁡(x,y)=x×y÷gcd⁡(x,y)\operatorname{lcm}(x,y)=x\times y\div\operatorname{gcd}(x,y)lcm(x,y)=x×y÷gcd(x,y)

所以说:

ans=change⁡(a)×change⁡(b)÷gcd⁡(change(a)⁡,change(b)⁡) mod mans=\operatorname{change}(a)\times\operatorname{change}(b)\div\operatorname{gcd}(\operatorname{change(a)},\operatorname{change(b)})\bmod mans=change(a)×change(b)÷gcd(change(a),change(b))modm

但我们仔细发现:gcd⁡(change⁡(a),change⁡(b))\operatorname{gcd}(\operatorname{change}(a),\operatorname{change}(b))gcd(change(a),change(b)) 这东西也不好求啊,如果我们能把它转化成 aaabbb 之间的关系就好了。

那么接下来,让我们用感性的思维去看一看这个式子,直觉告诉我们:gcd⁡(change⁡(a),change⁡(b))=change⁡(gcd⁡(a,b))\operatorname{gcd}(\operatorname{change}(a),\operatorname{change}(b))=\operatorname{change}(\operatorname{gcd}(a,b))gcd(change(a),change(b))=change(gcd(a,b))。以下是证明过程。

证明: 假设 1111...11⏟t个1\underbrace{1111...11}_{t\text{个}1}t11111...11 同时是 11111...11⏟a个1\underbrace{11111...11}_{a\text{个}1}a111111...11111111...11⏟b个1\underbrace{111111...11}_{b\text{个}1}b1111111...11 的公因数,则:

111111...11⏟b个1=1111...11⏟t个1×1000...00⏟t−1个01000...00⏟t−1个01...1000...00⏟t−1个0111111...11⏟a个1=1111...11⏟t个1×1000...00⏟t−1个01000...00⏟t−1个01...1000...00⏟t−1个01\underbrace{111111...11}_{b\text{个}1}=\underbrace{1111...11}_{t\text{个}1}\times1\underbrace{000...00}_{t-1\text{个}0}1\underbrace{000...00}_{t-1\text{个}0}1...1\underbrace{000...00}_{t-1\text{个}0}1\\\underbrace{11111...11}_{a\text{个}1}=\underbrace{1111...11}_{t\text{个}1}\times1\underbrace{000...00}_{t-1\text{个}0}1\underbrace{000...00}_{t-1\text{个}0}1...1\underbrace{000...00}_{t-1\text{个}0}1b1111111...11=t11111...11×1t10000...001t10000...001...1t10000...001a111111...11=t11111...11×1t10000...001t10000...001...1t10000...001

第一个式子中 000...00⏟t−1个01\underbrace{000...00}_{t-1\text{个}0}1t10000...001 这样的循环一共有 bt\frac{b}{t}tb 个,第二个式子中这样的循环则有 at\frac{a}{t}ta 个,因为要有整数个循环,所以 bt\frac{b}{t}tbat\frac{a}{t}ta 都是整数,所以 ttta,ba,ba,b 的公因数。而我们要 1111...11⏟t个1\underbrace{1111...11}_{t\text{个}1}t11111...11 最大,所以 ttt 就要是 a,ba,ba,b 的最大公因数,即 t=gcd⁡(a,b)t=\operatorname{gcd}(a,b)t=gcd(a,b)

由上,我们可以得到:

gcd⁡(11111...11⏟a个1,111111...11⏟b个1)=111111...11⏟t个1=111111...11⏟gcd⁡(a,b)个1\operatorname{gcd}(\underbrace{11111...11}_{a\text{个}1},\underbrace{111111...11}_{b\text{个}1})=\underbrace{111111...11}_{t\text{个}1}=\underbrace{111111...11}_{\operatorname{gcd}(a,b)\text{个}1}gcd(a111111...11,b1111111...11)=t1111111...11=gcd(a,b)1111111...11

转化一下就成了:

gcd⁡(change⁡(a),change⁡(b))=change⁡(gcd⁡(a,b))\operatorname{gcd}(\operatorname{change}(a),\operatorname{change}(b))=\operatorname{change}(\operatorname{gcd}(a,b))gcd(change(a),change(b))=change(gcd(a,b))

所以,我们得到了这样一个等式:

ans=change⁡(a)×change⁡(b)÷change⁡(gcd⁡(a,b))ans=\operatorname{change}(a)\times\operatorname{change}(b)\div\operatorname{change}(\operatorname{gcd}(a,b))ans=change(a)×change(b)÷change(gcd(a,b))

但这样我们又要算三遍 change⁡(x)\operatorname{change}(x)change(x),有没有什么办法可以优化?

这里呢我是采用了倍分的思想。

在上面的证明过程中,我们将 111111...11⏟b个1\underbrace{111111...11}_{b\text{个}1}b1111111...11 拆成了 1111...11⏟t个1×1000...00⏟t−1个01000...00⏟t−1个01...1000...00⏟t−1个01\underbrace{1111...11}_{t\text{个}1}\times1\underbrace{000...00}_{t-1\text{个}0}1\underbrace{000...00}_{t-1\text{个}0}1...1\underbrace{000...00}_{t-1\text{个}0}1t11111...11×1t10000...001t10000...001...1t10000...001,我们沿用这个思路,如果我们把 change⁡(a)\operatorname{change}(a)change(a) 归为一类,change⁡(b)÷change⁡(gcd⁡(a,b))\operatorname{change}(b)\div\operatorname{change}(\operatorname{gcd}(a,b))change(b)÷change(gcd(a,b)) 归为一类,那我们就只需要解决后半部分值的问题就行了,后半部分又该怎么做呢?

我们将这个式子转化一下,就成了:

change⁡(b)÷change⁡(t)=111111...11⏟b个1÷1111...11⏟t个1=1000...00⏟t−1个01000...00⏟t−1个01...1000...00⏟t−1个01 \begin{equation}\begin{split}&\operatorname{change}(b)\div\operatorname{change}(t)\\&=\underbrace{111111...11}_{b\text{个}1}\div\underbrace{1111...11}_{t\text{个}1}\\&=1\underbrace{000...00}_{t-1\text{个}0}1\underbrace{000...00}_{t-1\text{个}0}1...1\underbrace{000...00}_{t-1\text{个}0}1\end{split}\end{equation}change(b)÷change(t)=b1111111...11÷t11111...11=1t10000...001t10000...001...1t10000...001

而这又有 bt\frac{b}{t}tb 个循环,因为 t=gcd⁡(a,b)t=\operatorname{gcd}(a,b)t=gcd(a,b),所以就有 b÷gcd⁡(a,b)b\div\operatorname{gcd}(a,b)b÷gcd(a,b) 个循环。到这,整个思路就彻底结束了。

代码实现:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b,m;
int gcd(int x,int y) {
	if(y==0) {
		return x;
	}
	return gcd(y,x%y);
}
int qpow(int x,int y) {//快速幂
	int z=1;
	while(y) {
		if(y&1) {
			z=z*x%m;
		}
		y>>=1;
		x=x*x%m;
	}
	return z;
}
int answer(int x,int y) {
	int now=1,po=qpow(10,y),ans=0;
	while(x) {
		if(x&1) {
			ans=(ans*po%m+now)%m;
		}
		x>>=1;
		now=(now*po%m+now)%m;
		po=po*po%m;
	}
	return ans;
}
signed main() {
	cin>>a>>b>>m;
	int g=gcd(a,b);
	cout<<answer(a,1)*answer(b/g,g)%m;//一共有b/g个循环,每次要乘10^g
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值