HDU6627 equation

题目链接

题意:

两个长度为\(n\)的数组\(a\)\(b\)和一个正整数\(C\),计算有多少个\(x\)满足:
\[ \sum_{i=1}^n|a_i \cdot x+b_i|=C \]

思路:

该函数为分段函数,每段的转折点为\(-\frac{b_i}{a_i}\),先把转折点排序,计最开始的函数值为\(x \cdot suma + sumb\),每过一段,就会有一个\(|a_i \cdot x+b_i|\)\(a_i \cdot x+b_i\)变为\(-a_i \cdot x - b_i\),那么\(suma-2 \cdot a_i\),\(sum_b\)变为 \(sumb-2 \cdot b_i\)。每段函数都是线性的,大力枚举计算即可。然后对答案进行排序(博主忘记排序结果Wa到爆炸)。

代码:

#include<bits/stdc++.h>

using namespace std;
const int N = 2e5+100;
struct node{
    long long a,b;
}s[N];
int n;double c;
bool cmp(node x,node y){
    return (x.b*y.a)<(x.a*y.b);
}
bool cmp2(pair<long long, long long> a,pair<long long,long long> b){
    return a.first*b.second<a.second*b.first;
}
vector<pair<long long,long long>> ans;
void make(long long x,long long y){
    if(x==0){
        y=1;
        ans.push_back({x,y});return ;
    }
    long long gg=__gcd(x,y);
    x/=gg;y/=gg;
    if(y<=0){
        x=-x;y=-y;
    }
    ans.push_back({x,y});
    return ;
}
void solve(){
    ans.clear();
    scanf("%d %lf",&n,&c);
    long long sa=0;long long sb=0;
    for(int i=1;i<=n;i++){
         scanf("%lld %lld",&s[i].a,&s[i].b);
         sa+=s[i].a;
         sb+=s[i].b;
    }
    sort(s+1,s+n+1,cmp);
    double up=9999999999999;
    double down=-1.0*double(s[1].b*sa)/double(s[1].a)+sb;
    if(c>=down&&c<=up){
        long long u=(long long)c-sb;
        long long d=sa;
        make(u,d);
    }
    bool flag=0;
    for(int i=2;i<=n;i++){
        double nowr=(-1.0*double(s[i].b)*(sa-2*s[i-1].a)/double(s[i].a))+(sb-2*s[i-1].b);
        double bef=(-1.0*double(s[i-1].b)/double(s[i-1].a))*(sa)+(sb);
        up=max(nowr,bef);
        down=min(nowr,bef);
        if(up==down&&up==c){
            flag=1;break;
        }
        sa-=2*s[i-1].a;
        sb-=2*s[i-1].b;
        if(c>=down&&c<=up){
            long long u=(long long)c-sb;
            long long d=sa;
            make(u,d);          
        }
    }
    sa-=2*s[n].a;
    sb-=2*s[n].b;
    up=9999999999999;
    down=-1.0*double(s[n].b*sa)/double(s[n].a)+sb;
    if(c>=down&&c<=up){
        long long u=c-sb;
        long long d=sa;
        make(u,d);
    }
    if(flag) puts("-1");
    else{
        sort(ans.begin(),ans.end(),cmp2);
        int siz=unique(ans.begin(),ans.end())-ans.begin();
        printf("%d",siz);
        for(int i=0;i<(int)siz;i++) printf(" %lld/%lld", ans[i].first,ans[i].second);
        puts("");
    }
}
int main(){
    int T;scanf("%d",&T);
    while(T--) solve();
    return 0;
}

/*
2 6
0 4
-2 -6
*/

猜你喜欢

转载自www.cnblogs.com/codancer/p/12232406.html
今日推荐