题目要求找到给定区间的化简后分子分母的和小于1000的数字的个数
我的想法是先找到所有的满足要求的最简分数(总数不超过1e6,而且远小于),然后对询问查找每个最简分数出现的次数.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cctype>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e3+5;
struct node
{
int x,y;
}aa[MAXN*MAXN];
int tot;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
void init()
{
tot=0;
for(int i=1;i<999;i++)
{
aa[tot].x=1; aa[tot].y=i;
tot++;
}
for(int i=2;i<999;i++)
{
aa[tot].x=i; aa[tot].y=1;
tot++;
}
for(int i=2;i<1000;i++)
{
for(int j=2;j<1000;j++)
{
if(i+j>=1000) break;
if(gcd(i,j)!=1) continue;
aa[tot].x=i; aa[tot].y=j;
tot++;
}
}
}
ll A,B,C,D;
ll ans,k1,k2,k3,k4;
ll deal(ll a,ll b,ll c,ll d)
{
if(a>b || c>d) return 0;
if(c>b || d<a) return 0;
ll x=max(a,c);
ll y=min(b,d);
return y-x+1;
}
int main()
{
//freopen("data.in","r",stdin);
init();
while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&D))
{
ans=0;
for(int i=0;i<tot;i++)
{
if(A%aa[i].x==0) k1=A/aa[i].x;
else k1=A/aa[i].x+1;
k2=B/aa[i].x;
if(C%aa[i].y==0) k3=C/aa[i].y;
else k3=C/aa[i].y+1;
k4=D/aa[i].y;
ll tmp=deal(k1,k2,k3,k4);
if(tmp>0)
{
ans+=tmp;
//printf("%d/%d %d\n",aa[i].x,aa[i].y,tmp);
}
}
printf("%lld\n",ans);
}
return 0;
}