洛谷 P6511 [QkOI#R1] Quark and Equations 数学
首先要进行一些特判:
-
当 或 或 时,结果为
-
当 或 时,结果为
此时 ,对 和 这两种情况分别进行讨论:
- 时,原式子变成
由于 ,因此上式等价于:
再代入 得:
因此转化为 时,有多少个 满足式 。
- 时,原式子变成
因此转化为 时,有多少个 满足式 。
然后可以推出各自的范围:
时:
时:
因此得到两个不等式组:
因此最终的答案就是
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int T;
ll n,m;
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&n,&m);
ll res=0;
if(m==1||m>n||n==1)res=0;
else if(m==n||m==n-1)res=1;
else res=(n-1)/m-(n-1)/(m+1)+n/m-n/(m+1);
printf("%lld\n",res);
}
return 0;
}
当时我是用分块做的:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int T;
ll n,m;
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&n,&m);
ll res=0;
if(m==1||m>n||n==1)res=0;
else if(m==n||m==n-1)res=1;
else{
//if(m==2&&(n%2==0))res++;
ll k;
ll i=(n-1)/(m+1);
for(;i<=(n-1)/2;i=k+1){
k=(n-1)/((n-1)/i);
if((n-1)/i==m){
res+=k-i+1;
break;
}
}
ll j=n/(m+1);
for(;j<=(n-1)/2;j=k+1){
k=n/(n/j);
if(n/j==m){
res+=k-j+1;
break;
}
}
}
printf("%lld\n",res);
}
return 0;
}