18届科大讯飞杯

18届科大讯飞杯


太懒了,一直放着没怎么补


D.最大字符集

题意:

18届科大讯飞杯_第1张图片

解法:

思维构造题

把n=1和n=2的时候特判掉
其他情况下都可以输出n-1种
00
010
0110
01110

code:
#include
using namespace std;
signed main(){
    int n;cin>>n;
    if(n==1)puts("1\n1\n");
    else if(n==2)puts("2\n1\n00\n");
    else{
        cout<<n-1<<endl;
        for(int i=2;i<=n;i++){
            string ans="0";
            for(int j=2;j<=i-1;j++){
                ans+='1';
            }
            ans+='0';
            cout<<ans<<endl;
        }
    }
    return 0;
}

L.动物森友会

题意:

18届科大讯飞杯_第2张图片

解法:

满足单调性,因此可以二分

二分天数,用最大流check

源点连接一周的7天,边权为(mid/7)*e,取余多出来的也要加进去
每天连接这一天所能做的事件,边权为inf
每个事件连接汇点,边权为该事件需要完成的数量

如果最大流等于所有事件需要完成的数量总和,则满足,否则不满足

code:
#include
using namespace std;
#define int long long
const int maxm=1e4+5;
vector<int>g[10];
int head[maxm],nt[maxm<<1],to[maxm<<1],w[maxm<<1],cnt;
int c[maxm],sum;
int d[maxm];
int n,e;
void init(){
    memset(head,0,sizeof head);
    cnt=1;
}
void add(int x,int y,int z){
    cnt++;nt[cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;
}
bool bfs(int st,int ed){
    memset(d,0,sizeof d);
    d[st]=1;
    queue<int>q;
    q.push(st);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=nt[i]){
            int v=to[i];
            if(w[i]&&!d[v]){
                d[v]=d[x]+1;
                q.push(v);
                if(v==ed)return 1;
            }
        }
    }
    return 0;
}
int dfs(int x,int ed,int flow){
    if(x==ed)return flow;
    int res=flow;
    for(int i=head[x];i;i=nt[i]){
        int v=to[i];
        if(w[i]&&d[v]==d[x]+1){
            int k=dfs(v,ed,min(res,w[i]));
            w[i]-=k;
            w[i^1]+=k;
            res-=k;
            if(!k)d[v]=-1;
            if(!res)break;
        }
    }
    return flow-res;
}
int dinic(int st,int ed){
    int ans=0;
    while(bfs(st,ed))ans+=dfs(st,ed,1e18);
    return ans;
}
int cc[maxm];
int day[10];
bool check(int mid){
    init();
    int tot=0;
    int st=++tot,ed=++tot;//源汇点
    for(int i=1;i<=n;i++)cc[i]=++tot;//事件点
    for(int i=1;i<=7;i++)day[i]=++tot;//周1到周7的点
    for(int i=1;i<=n;i++){//事件->汇点,边权为c[i]
        add(cc[i],ed,c[i]);
        add(ed,cc[i],0);
    }
    for(int i=1;i<=7;i++){
        int t=(mid/7+(mid%7>=i))*e;
        add(st,day[i],t);
        add(day[i],st,0);
    }
    for(int i=1;i<=7;i++){
        for(int v:g[i]){
            add(day[i],cc[v],1e18);
            add(cc[v],day[i],0);
        }
    }
    int ans=dinic(st,ed);
    return ans==sum;
}
signed main(){
    cin>>n>>e;
    for(int i=1;i<=n;i++){
        cin>>c[i];
        sum+=c[i];//sum记录总次数
        int k;cin>>k;
        while(k--){
            int x;cin>>x;
            g[x].push_back(i);
        }
    }
    int l=1,r=1e9;
    int ans=-1;
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<endl;
    return 0;
}

你可能感兴趣的:(18届科大讯飞杯)