D题我的做法(多项式复杂度)
我的做法是先把负数变成正数,然后去枚举负数是哪些
具体做法如下:
首先,把负数加进集合可以看作整体加一个数字,然后加进集合变成不在这个集合内部
换句话说,也就是x加到集合变成-x从集合中删除
由于是给的是所有集合sum的cnt,所以如果把所有负数都变成-x,得到的新的集合 等价于 给定的集合都加上负的最小的集合sum(这个东西显然是所有负数之和)得到的集合
然后集合中就没有了负数,我们考虑全是正数的话,怎么做
全是正数的话,我们从小往大考虑集合中的元素,一定可以贪心的获得唯一的集合(好像是前几年的多校有道水题和这个一样)
然后考虑负数的和是原来加上的那个sum。这里我们可以用背包来做即可。(任何和是这个sum的方案都是对的)
复杂度:O(T*n*|S|*log(n)),这个log(n)是用set的复杂度,这里可以哈希去掉这个log
我这个背包写的挺丑的也过了,说明这个显然时间复杂度不满,常数很小
#include <sstream> #include <fstream> #include <cstdio> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <string> #include <cstring> #include <stack> #include <queue> #include <cmath> #include <ctime> #include <utility> #include <cassert> #include <bitset> using namespace std; #define REP(I,N) for (I=0;I<N;I++) #define rREP(I,N) for (I=N-1;I>=0;I--) #define rep(I,S,N) for (I=S;I<N;I++) #define rrep(I,S,N) for (I=N-1;I>=S;I--) #define FOR(I,S,N) for (I=S;I<=N;I++) #define rFOR(I,S,N) for (I=N;I>=S;I--) #define DEBUG #ifdef DEBUG #define debug(...) fprintf(stderr, __VA_ARGS__) #define deputs(str) fprintf(stderr, "%s\n",str) #else #define debug(...) #define deputs(str) #endif // DEBUG typedef unsigned long long ULL; typedef unsigned long long ull; typedef long long LL; typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll; const int INF=0x3f3f3f3f; const LL INFF=0x3f3f3f3f3f3f3f3fll; const LL M=1e9+7; const LL maxn=10000+7; const double pi=acos(-1.0); const double eps=0.0000000001; LL gcd(LL a, LL b) {return b?gcd(b,a%b):a;} template<typename T>inline void pr2(T x,int k=64) {ll i; REP(i,k) debug("%d",(x>>i)&1); putchar(' ');} template<typename T>inline void add_(T &A,int B,ll MOD=M) {A+=B; (A>=MOD) &&(A-=MOD);} template<typename T>inline void mul_(T &A,ll B,ll MOD=M) {A=(A*B)%MOD;} template<typename T>inline void mod_(T &A,ll MOD=M) {A%=MOD; A+=MOD; A%=MOD;} template<typename T>inline void max_(T &A,T B) {(A<B) &&(A=B);} template<typename T>inline void min_(T &A,T B) {(A>B) &&(A=B);} template<typename T>inline T abs(T a) {return a>0?a:-a;} template<typename T>inline T powMM(T a, T b) { T ret=1; for (; b; b>>=1ll,a=(LL)a*a%M) if (b&1) ret=(LL)ret*a%M; return ret; } int n,m,q; char str[maxn]; int startTime; void startTimer() {startTime=clock();} void printTimer() {debug("/--- Time: %ld milliseconds ---/\n",clock()-startTime);} vector<ll> Ans,ans; ll S[maxn],P[maxn]; map<ll,ll> now,nxt; inline int getid(ll x){ int ret=lower_bound(S+1,S+1+n,x)-S; if (ret<=n&&S[ret]==x) return ret; return -1; } pair<ll,ll> H[maxn]; pii pre[107][maxn]; int solve(int T){ int i,j; scanf("%d",&n); FOR(i,1,n) scanf("%lld",&H[i].first); FOR(i,1,n) scanf("%lld",&H[i].second); sort(H+1,H+1+n); FOR(i,1,n) S[i]=H[i].first,P[i]=H[i].second; ll MIN=-S[1]; P[1]--; FOR(i,1,n) S[i]+=MIN; now.clear(); now[0]++; Ans.clear(); ans.clear(); FOR(i,1,n){ while (P[i]){ // printf("i=%d P=%lld\n",i,P[i]); // for (auto x:now) printf("%lld(%lld) ",x.first,x.second);puts(""); Ans.push_back(S[i]); for (auto x:now){ P[getid(x.first+S[i])]-=x.second; nxt[x.first+S[i]]+=x.second; nxt[x.first]+=x.second; } swap(nxt,now); nxt.clear(); } } // for (int v:Ans) printf("%lld ",S[v]);puts(""); FOR(i,1,n) pre[0][i]=make_pair(0,0); pre[0][1]=make_pair(0,1); REP(i,(int)Ans.size()){ FOR(j,1,n) pre[i+1][j]=pre[i][j]; rFOR(j,1,n) if (pre[i][j]!=make_pair(0,0)){ int nxtid=getid(S[j]+Ans[i]); if (nxtid!=-1) pre[i+1][nxtid]=make_pair(i,j); } } int last=getid(MIN); i=Ans.size(); while (last!=1){ auto nxt=pre[i][last]; ans.push_back(-(S[last]-S[nxt.second])); last=nxt.second; i=nxt.first; }last=ans.size()-1; REP(i,(int)Ans.size()){ if (last!=-1&&ans[last]+Ans[i]==0) last--; else ans.push_back(Ans[i]); } printf("Case #%d:",T); for (ll now:ans) printf(" %lld",now);puts(""); return 0; } int main() { int T,i; scanf("%d",&T); FOR(i,1,T) solve(i); } /* */