隐藏
「NOIP十连赛day5」方程simple - 数学+模拟 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「NOIP十连赛day5」方程simple - 数学+模拟

题目大意

对于给定正整数n,m,我们称正整数c为好的,当且仅当存在非负整数x,y,使得$nx+my=c$。
现在给出多组数据,对于每组数据,给定n,m,q,求[1,q]内有多少个正整数不是好的。
n≤10^5 , m≤10^9 , q≤10^18 , T≤10


题目分析

由题,$nx+my=c$该式完全对称,但是$n$与$m$的范围却不一样,这说明我们需要往$n$的方向考虑。

我们发现有如下式子:

因此我们可以枚举$y$,可以发现不超过$n$个必定有循环
如果有循环,那么 $y$小一些的方案必定包含$y$大一些的方案。
因此我们只需枚举$y$,即可得到$ym$的值。
题目要求$nx+my\in[1,q]$,那么我们只需要考虑$nx$的值即可,我们可以$O(1)$计算出$nx+ym$在区间$[1,q]$的个数,即可得出答案。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;
inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
LL t,n,m,q,ans=0;
int main() {
t=Get_Int();
while(t--) {
n=Get_Int(),m=Get_Int(),q=Get_Int();
ans=q/n+1;
LL sum=0,tmp=0;
for(int i=1; i<=n; i++) {
tmp=(tmp+m)%n;
sum+=m;
if(tmp==0||sum>q)break;
ans+=(q-sum)/n+1;
}
printf("%lld\n",q-ans+1);
}
return 0;
}
姥爷们赏瓶冰阔落吧~