P8249 模法问题 题解
题目传送门
显然,这道题不能用暴力做,因为仅仅计算单个的问题,就会达到
这个时候就需要考虑其他方法了。
因为这道题求的是余数的和,所以 最理想 的情况答案应为
我们可以新建一个变量
if(l \ t != r \ t)
不过,当
因为本蒟蒻不会倍增算法,所以 我们可以另辟蹊径。通过观察可以发现,在单独对一个数取余的两个序列中,会出现余数为
所以如果有一列的数右边都不是
总结一下:
如果区间内存在最理想情况,直接输出。如果不存在,扫描一遍所有的
上代码:
#include<bits/stdc++.h>
using namespace std;
int a,b,q,l,r,t,minn,maxn,ans;
int gcd(int a,int b)//最大公约数
{
if(a % b == 0) return b;
else return gcd(b,a % b);
}
int calc(int x)//计算结果
{
return x % a + x % b;
}
signed main()
{
std::ios::sync_with_stdio(false);
cin>>a>>b;
t = gcd(a,b);
t = a * b / t;
cin>>q;
for(int i=0;i<q;i++)
{
cin>>l>>r;
minn = l / t;
maxn = r / t;
ans = 0;
if(minn != maxn) cout<<calc(maxn*t-1)<<endl;//最理想情况
else
{
ans = calc(r);//千万别忘了扫这个位置
for(int i = r/a*a-1;i>=l;i-=a) ans = max(ans,calc(i));//扫一遍除以第一个数余0的位置的左边并取最大值
for(int i = r/b*b-1;i>=l;i-=b) ans = max(ans,calc(i));//扫一遍除以第二个数余0的位置的左边并取最大值
cout<<ans<<endl;
}
}
return 0;
}