题目
思路(找规律题目)
列几个式子:
a
L
+
k
0
=
n
aL+k_0=n
aL+k0=n
a ( L + 1 ) + k 1 = n a(L+1)+k_1=n a(L+1)+k1=n
…
a
(
L
+
c
)
+
k
c
=
n
a(L+c)+k_c=n
a(L+c)+kc=n
b ( L + c + 1 ) + k c + 1 = n b(L+c+1)+k_{c+1}=n b(L+c+1)+kc+1=n
…
可以发现,当整除
i
i
i 时的商相同时,余数递减。我们可以从小到大“跳商”,经验证,时间复杂度大概
O
(
N
)
O(\sqrt N)
O(N)
怎么跳呢?
- 求出 a = N / L a=N/L a=N/L
- 再可以得到
L
+
c
=
N
/
a
L+c=N/a
L+c=N/a
(如果 N / a < L + c N/a<L+c N/a<L+c 小的话,不妨设 a ( L + c 0 ) + k = n a(L+c_0)+k=n a(L+c0)+k=n,明显矛盾)
具体数学原理我也不是很清楚,希望有大佬能够教一教。
时间复杂度是验证得出的,数学证明也不是很会。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#define mez(x) memset(x,0,sizeof x)
#define mei(x) memset(x,0x3f,sizeof x)
#define lowbit(x) -x&x
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define cu(x) cout<<x<<"--"<<endl
#define ex exit(0)
#define pn puts("")
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> vc;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main()
{
ll n,m,i,l,r,ans;
scanf("%lld%lld",&n,&m);
while(m--)
{
scanf("%lld%lld",&l,&r);
ans=0;
for(i=l;i<=r;i=n/(n/i)+1)
ans=max(ans,n%i);
printf("%lld\n",ans);
}
return 0;
}