其他分享
首页 > 其他分享> > C20220805T3 零和

C20220805T3 零和

作者:互联网

当构造出长度为22的随机 \([1,5]\) 的集合后,出现合法方案的概率很大,所以可以先随便构造一种方案,然后再通过背包求出其他取值中可以满足的方案数(即先构造22个极小的整数,去找到其他负数,并将这几个负数以01背包的方式求出对应的方案数),最后离线 \(t\) 组询问,若有解就继续,若无解就重新构造,最后一个点正好跑到1000ms(时限2000ms),时间充裕。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mp std::make_pair
#define pii std::pair<int,int>
#define chkmin(_A,_B) (_A=std::min(_A,_B))
#define chkmax(_A,_B) (_A=std::max(_A,_B))
//--------------------FastInOut--------------------//
class IO{
    public:
        inline char read(){
            static const int IN_LEN =1<<18|1;
            static char buf[IN_LEN],*s,*t;
            return (s==t)&&(t=(s=buf)+fread(buf, 1, IN_LEN, stdin)),(s==t)?-1:*s++;
        }
        template<typename _Tp>inline IO &operator >>(_Tp &x){
            static char c11, boo;
            for (c11=read(),boo=0;!isdigit(c11);c11=read()) {
                if (c11==-1)
                    return *this;
                boo|=(c11=='-');
            }
            for(x=0;isdigit(c11);c11=read())
                x=x*10+(c11^'0');
            if(boo)
                x=-x;
            return *this;
        }
        inline void push(const char &c) {
            putchar(c);
        }
        template<typename _Tp>inline IO &operator <<( _Tp x){
            if (x<0)
                x=-x,push('-');
            static _Tp sta[35];
            _Tp top=0;
            do{
                sta[top++]=x%10,x/=10;
            }while(x);
            while(top)
                push(sta[--top]+'0');
            return *this;
        }
        inline IO &operator <<(char lastChar){
            push(lastChar);
            return *this; 
        }
}FIO;

int rd[30];
std::vector<int> v;
int dp[205];
int head[1000005],to[40000005],nxt[40000005],id[40000005],ecnt,sum;
int vis[1000005],pre[1000005],lst[1000005];
void add(int u,int v,int w) {
    nxt[++ecnt]=head[u];
    to[ecnt]=v;
    id[ecnt]=w;
    head[u]=ecnt;
}
void print(int x,std::vector<int> &ans) {
    if (!x)
        return;
    ans.push_back(-pre[x]);
    print(lst[x], ans);
}
int main(){
    freopen("zero.in","r",stdin);
    freopen("zero.out","w",stdout);
    for(int i=1;i<=22;++i){
        rd[i]=rand()%5+1;
        sum+=rd[i];
        v.push_back(rd[i]);
    }
    dp[0]=1;
    for(int i=1;i<=22;++i){
        for(int j=sum;j>=rd[i];--j){
            dp[j]+=dp[j-rd[i]];
        }
    }
    for(int i=0;i<=1000000;i++){
        for (int j=std::max(1,sum-40);j<=sum;j++){
            if (i+dp[j]<=1000000){
                add(i,i+dp[j],j);
            }
        }
    }
    std::queue<int> q;
    q.push(0);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=1;
        for (int i=head[x];i;i=nxt[i]) {
            if (!vis[to[i]]){
                vis[to[i]]=1;
                pre[to[i]]=id[i];
                lst[to[i]]=x;
                q.push(to[i]);
            }
        }
    }
    int T;
    FIO>>T;
    while(T--){
        int x;
        FIO>>x;
        while(1){
            std::vector<int> ans=v;
            print(x-1,ans);
            if(ans.size()<=30){
                FIO<<ans.size()<<'\n';
                for (int i=0;i<(int)ans.size();++i)
                    FIO<<ans[i]<<' ';
                FIO<<'\n';
                break;
            }
            sum=0;
            memset(dp,0,sizeof(dp));
            memset(head,0,sizeof(head));
            memset(vis,0,sizeof(vis));
            v.clear();
            ecnt=0;
            for(int i=1;i<=22;++i){
                rd[i]=rand()%5+1;
                sum+=rd[i];
                v.push_back(rd[i]);
            }
            dp[0]=1;
            for(int i=1;i<=22;++i){
                for(int j=sum;j>=rd[i];--j){
                    dp[j]+=dp[j-rd[i]];
                }
            }
            for(int i=0;i<=1000000;i++){
                for (int j=std::max(1,sum-40);j<=sum;j++){
                    if (i+dp[j]<=1000000){
                        add(i,i+dp[j],j);
                    }
                }
            }
            std::queue<int> q;
            q.push(0);
            while(!q.empty()){
                int x=q.front();
                q.pop();
                vis[x]=1;
                for (int i=head[x];i;i=nxt[i]) {
                    if (!vis[to[i]]){
                        vis[to[i]]=1;
                        pre[to[i]]=id[i];
                        lst[to[i]]=x;
                        q.push(to[i]);
                    }
                }
            }
        }
    }
    return 0;
}

标签:std,vis,C20220805T3,int,push,c11,define
来源: https://www.cnblogs.com/zhouzizhe/p/16642688.html