2019hdu暑假多校第5场1004 equation HDU - 6627
You are given two integers N,CN,C and two integer sequences aa and bb of length NN. The sequences are indexed from 11 to NN.
Please solve the following equation for xx:
∑i=1N|ai⋅x+bi|=C∑i=1N|ai⋅x+bi|=C, where |v||v| means the absolute value of vv.
题意:
给出2个数N,c。然后给出长度为N的2个序列a,b。列出等式|a1*x+b1|+|a2*x+b2|+|a3*x+b3|+......|an*x+bn|=c.
问x的解的个数,如果有无穷个输出-1.否则,输出个数之后,按x/y(x,y均为int型)的格式输出所有答案。
思路:
对于每一对ai,bi。维护一个double 型的p=1.0*ai/bi。然后可以想到,按p分区间,可以分出N+1个区间。
从最左边往右,分别表示有0个绝对值内为正,有1个绝对值内为正。。。。有i个绝对值内为正。
对于第i个区间,我们可以用O(1)的复杂度求出x的系数和记为A,以及等号左边的常数记为B。
我们不妨把ai,bi按pi进行排序。那么到底i个区间时,即为aj*x+bj>0(j<=i)。我们一开始令A=-a1-a2-a3......-aN,B=-b1-b2-b3......-bN.那么每一次我们只需A+=2*ai,B+=2*bi.
即为当前区间对应的A,B。那么我们就可以求出一个对应的x。然后判一下所求的x是否在区间内就可以了。
对于无穷答案的情况就是A==0&&B==c。在A==0的时候特判一下就好了。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | #include<bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1e5+5; struct node { int a,b; double p; } gj[maxn]; struct nodee { int a,b; } ans[maxn],an[maxn]; bool cmp(node x,node y) { return x.p<y.p; } int main() { //freopen("1.in","r",stdin); int t,cas=0; scanf ( "%d" ,&t); while (t--) { int n,c; scanf ( "%d%d" ,&n,&c); for ( int i=1; i<=n; i++) { int a,b; scanf ( "%d%d" ,&gj[i].a,&gj[i].b); gj[i].p=-(gj[i].b*1.0)/gj[i].a; } sort(gj+1,gj+1+n,cmp); int A=0,B=0; for ( int i=1; i<=n; i++) { A-=gj[i].a; B-=gj[i].b; } int cnt = 0,ok=0; double pre=-1e10; gj[0].a=gj[0].b=0; gj[n+1].a=gj[n+1].b=0; for ( int i=0; i<=n;) { do { A+=2*gj[i].a; B+=2*gj[i].b; } while (i<=n&&gj[i+1].p==gj[i++].p); //会出现相同的p,所以要把相同的p放在一起算。 if (A==0&&B!=c) { pre=-1.0*gj[i].b/gj[i].a; continue ; } else if (A==0&&B==c) { ok=1; //无穷个解 break ; } else { int x=c-B,y=A; int X= abs (x),Y= abs (y); int z=__gcd(X,Y); x/=z; y/=z; double tmp = x*1.0/y; double ttt; if (i==n+1)ttt=1e17; else ttt=-1.0*gj[i].b/gj[i].a; if (pre<=tmp&&tmp<=ttt) //判断答案是否在边界内 { ans[cnt].a=x; ans[cnt++].b=y; } } pre=-1.0*gj[i].b/gj[i].a; } if (ok) puts ( "-1" ); else if (cnt == 0) puts ( "0" ); else { int num=0; for ( int i=0; i<cnt; i++) { if ((ans[i].a>0&&ans[i].b>0)||(ans[i].b<0&&ans[i].a<0)) ans[i].a= abs (ans[i].a),ans[i].b= abs (ans[i].b); else if (ans[i].a>0&&ans[i].b<0) { ans[i].b=-ans[i].b,ans[i].a=-ans[i].a; } else if (ans[i].a==0) ans[i].b=1; if (i) { if (!(ans[i].a==ans[i-1].a&&ans[i].b==ans[i-1].b)) an[num].a=ans[i].a,an[num++].b=ans[i].b; } else an[num].a=ans[i].a,an[num++].b=ans[i].b; } printf ( "%d " ,num); for ( int i=0; i<num; i++) { printf ( "%d/%d" ,an[i].a,an[i].b); if (i==num-1) puts ( "" ); else printf ( " " ); } } } return 0; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步