zoukankan      html  css  js  c++  java
  • bzoj 2797 [Poi2012]Squarks 枚举一个,推出所有

    题目大意

    设有n个互不相同的正整数{X1,X2,...Xn},任取两个Xi,Xj(i≠j),能算出Xi+Xj。
    现在所有取法共n*(n-1)/2个和,要你求出X1,X2,...Xn。
    输出所有满足条件的方案
    3<=n<=300

    分析

    首先我们假设x1<x2<x3..<xn是没问题的
    那么两个数的和中最小的为x1+x2
    次小的为x1+x3
    现在考虑x2+x3的排名
    比x2+x3小的一定是x1+xk
    我们枚举x2+x3是哪一个值
    可以解出x1,x2,x3
    剩下的数中最小的为x1+x4
    求出x4
    同时可以算出x2+x4,x3+x4
    除去已知的,剩下的数中最小x1+x5
    依此类推

    做法

    我们考虑怎么找剩下的数
    首先我们把所有的和插入set/heap里
    每知道一个和就在里面删掉
    考虑什么情况违法
    x<0, xi-1==xi ,你求出来的和在原序列中不存在

    solution

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cctype>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    const int M=307;
     
    inline int rd(){
        int x=0;bool f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
        for(;isdigit(c);c=getchar()) x=x*10+c-48; 
        return f?x:-x;
    }
     
    int n,m;
    int a[M];
    int b[M*M];
     
    int ans[M][M],tot;
     
    struct cmp{
        bool operator () (int x,int y){
            return x>y;
        }
    };
     
    priority_queue<int,vector<int>,cmp>q,ers;
     
    void gao(int d){
        int tp=b[1]+b[2]+d;
        if(tp&1) return;
        tp/=2;
        a[3]=tp-b[1];
        a[2]=tp-b[2];
        a[1]=tp-d;
         
        int cnt;
        int i,j,val;
         
        while(!q.empty()) q.pop();
        while(!ers.empty()) ers.pop();
        for(i=1;i<=m;i++) q.push(b[i]);
        ers.push(b[1]);
        ers.push(b[2]);
        ers.push(d);
         
        for(cnt=4;cnt<=n;cnt++){
            while(!ers.empty()){
                if(ers.top()==q.top()){
                    ers.pop();
                    q.pop();
                }
                else break;
            }
            val=q.top();q.pop();
            a[cnt]=val-a[1];
            for(j=2;j<cnt;j++) ers.push(a[j]+a[cnt]);
        }
         
        while(!ers.empty()){
            if(ers.top()==q.top()){
                ers.pop();
                q.pop();
            }
            else break;
        }
        if(!ers.empty()) return;
        for(i=1;i<=n;i++) if(a[i]<=0) return;
        for(i=2;i<=n;i++) if(a[i]==a[i-1]) return;
         
        tot++;
        for(i=1;i<=n;i++) ans[tot][i]=a[i];
    }
     
    int main(){
        int i,j;
        n=rd();
        m=n*(n-1)/2;
        for(i=1;i<=m;i++) b[i]=rd();
        sort(b+1,b+m+1);
         
        for(i=3;i<=n;i++)
            if(i==3||b[i]!=b[i-1]) gao(b[i]);
         
        printf("%d
    ",tot);
        for(i=1;i<=tot;i++){
            for(j=1;j<=n;j++) printf("%d ",ans[i][j]);
            puts("");
        }
    }
    
  • 相关阅读:
    HDU
    稀疏表(ST / Sparse Table)
    HDU
    HDU
    树状数组
    用 BitArray 来编写埃拉托斯特尼筛法
    BitArray 内置是逆序存储, 因此要自行实现正序输出
    位运算,位移,窗体
    按位运算,窗体程序,And,Or,Xor
    基数排序
  • 原文地址:https://www.cnblogs.com/acha/p/6407086.html
Copyright © 2011-2022 走看看