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;
}
T1

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);
}
T2

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 }
T3

 

posted on 2021-08-04 21:25  JYFHYX  阅读(30)  评论(0编辑  收藏  举报