题目描述:
给出N个Ai和N个Bi 求 解 X 的个数和分数表示,如果无穷个解请输出-1
题目分析:
高中解方程题目啊
首先 对于每个式子 我们可以找到一个特殊点 G 如果X<G 那么 |aix+bi|= -aix-bi
我们首先把每个式子的G解出来 也就是 (-bi/ai) 然后把这N个式子按照G的大小排序
这样就相当于把一个数轴划分成了N+1个区间,在每个区间里,都有一个不带绝对值的解析式
当我们通过O1的转移得出解析式来时,就可以O1的求出解X了,当然还要判断一下X是否在这个区间内。
对于无穷解的情况,就是存在这样的一个区间 系数Ai的和为0,而Bi的和为Ci,这时方程的值与X无关,区间内的所有值都是这个方程的解,也就是无限个解了。
时间复杂度O(N)
实名感谢出题人不卡Double…
题目链接:
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define int long long
const double inf=0x7fffffff;
const int maxm=1e5+100;
int n,c,cnt;
struct s{
int x1,x2;
double ps;
}ans[maxm];
struct node{
int a,b;
int x1,x2;
double js;
}e[maxm];
inline bool comp(node x,node y){return x.js<y.js;}
inline bool com2(s x,s y){return x.ps<y.ps;}
inline bool ok(s x)
{
for(int i=1;i<=cnt;i++) if((ans[i].x1==x.x1)&&(ans[i].x2==x.x2)) return 0;
return 1;
}
inline int abs(int x)
{
if(x<0) x=-x;
return x;
}
inline void work()
{
scanf("%lld%lld",&n,&c);
cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&e[i].a,&e[i].b);
e[i].js=(1.0*(-e[i].b))/(1.0*e[i].a);
}
std::sort(e+1,e+n+1,comp);
int nowa=0,nowb=0;
for(int i=1;i<=n;i++) nowa+=(-e[i].a),nowb+=(-e[i].b);
int now=0;
int flag=0;
while(1)
{
double l,r;
now==0?l=-inf:l=e[now].js;
now==n?r=inf:r=e[now+1].js;
s x=s{c-nowb,nowa,0.0};
double s=(1.0*c-1.0*nowb)/(1.0*nowa);
if((s>=l)&&(s<=r))
{
int g=std::__gcd(x.x1,x.x2);
x.x1/=g,x.x2/=g;
x.ps=s;
if(ok(x)) ans[++cnt]=x;
}
now++;
if(now==(n+1)) break;
nowa+=2*e[now].a,nowb+=2*e[now].b;
if((nowa==0)&&(nowb==c)) flag=1;
if(flag) break;
}
if(!flag)
{
printf("%lld",cnt);
if(cnt) printf(" ");
if(cnt) std::sort(ans+1,ans+cnt+1,com2);
for(int i=1;i<=cnt;i++)
{
if(ans[i].ps<0) printf("-");
if(!ans[i].x1) printf("0/1");
else printf("%lld/%lld",abs(ans[i].x1),abs(ans[i].x2));
if(i!=cnt) printf(" ");
}
}
else printf("-1");
puts("");
}
signed main()
{
int t;
scanf("%lld",&t);
for(int i=1;i<=t;i++) work();
return 0;
}