T1贸易陈
选学的呀批,优化了个暴力直接80了;
大部分有想法的暴力都在70到95不等
那么说下正解
meet in the middle 枚举前一半的所有差值情况和后一半的所有差值情况
然后俩dfs就行了
#include<bits/stdc++.h> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int a[21],vis[1<<20],n,tot; map<int ,int >m; vector<int >q[10000005]; void ldfs(int x,int res,int sta) { if(x==n/2+1) { if(m.find(res)==m.end()) m[res]=++tot; int now=m[res]; q[now].push_back(sta); return ; } ldfs(x+1,res,sta); ldfs(x+1,res+a[x],sta|(1<<(x-1))); ldfs(x+1,res-a[x],sta|(1<<(x-1))); } void rdfs(int x,int res,int sta) { if(x==n+1) { if(m.find(res)!=m.end()) { int now=m[res]; for(int i=0;i<q[now].size();i++) vis[q[now][i]|sta]=1; } return ; } rdfs(x+1,res,sta); rdfs(x+1,res+a[x],sta|(1<<(x-1))); rdfs(x+1,res-a[x],sta|(1<<(x-1))); } int main() { n=read();for(int i=1;i<=n;i++) a[i]=read(); ldfs(1,0,0);rdfs(n/2+1,0,0); int ans=0;for(int i=1;i<1<<n;i++) ans+=vis[i]; cout<<ans; }
T2猫儿陈
不会写,只能靠next_pomutation狗了20分
正解就是个n方的前缀和优化dp
#include<bits/stdc++.h> #define int long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int mod=1e9+7; const int maxn=5001;bool b[maxn]; int dp[maxn][maxn],a[maxn],n,ans=0,g[maxn][maxn]; signed main() { n=read(); for(int i=0;i<n;i++) a[i]=read();for(int i=0;i<n;i++) if(i<a[i]) {b[i-1]=1; b[a[i]-1]=1;} else for(int j=a[i];j<i-1;j++) b[j]=1; dp[0][1]=g[0][1]=1; for(int i=1;i<n-1;i++) for(int j=1;j<=i+1;j++) { if(b[i-1])dp[i][j]=(dp[i][j]+g[i-1][i]-g[i-1][j-1]+mod)%mod; else dp[i][j]=(dp[i][j]+g[i-1][j-1])%mod; g[i][j]=(g[i][j-1]+dp[i][j])%mod; } for(int i=1;i<n;i++) (ans+=dp[n-2][i])%=mod; printf("%lld\n",ans); }
T3毛三陈
垃圾玄学题,玄学复杂度,枚举x二分最大容量+减枝就过了
1 #include<bits/stdc++.h> 2 using namespace std; 3 inline int read() 4 { 5 int x=0,f=1;char ch=getchar(); 6 while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 8 return x*f; 9 } 10 int n,p,kk,from=132456,ans=80000,a[2000001],b[2000001]; 11 bool check(int x,int y) 12 { 13 int k=1,sum=0,res; 14 for(int i=1;i<=n;i++) 15 { 16 res=(a[i]+y)%p; 17 if(res>x) return 0; 18 if(sum+res<=x) sum+=res; 19 else {++k; sum=res;} 20 if(k>kk) return 0; 21 } 22 if(k<=kk) return 1; 23 else return 0; 24 } 25 void Mid(int x) 26 { 27 int l=1,r=ans,dd; 28 while(l<=r) 29 { 30 int mid=l+r>>1; 31 if(check(mid,x)) r=mid-1,dd=mid; 32 else l=mid+1; 33 } 34 ans=min(ans,dd); 35 } 36 int main() 37 { 38 n=read();p=read();kk=read(); 39 for(int i=1;i<=n;i++) 40 { 41 a[i]=read(); 42 from=min(p-a[i],from); 43 } 44 for(int i=from;i<p;i++) 45 { 46 if(check(ans,i)) 47 Mid(i); 48 else continue; 49 } 50 cout<<ans<<endl; 51 }