2019 Multi-University Training Contest 1

能写一点是一点吧

多校第一场由于某些不可抗力因素就没打

1001:

我们考虑dp[i][j][k][now](i<j<k<now)表示这四种颜色出现的最后的位置为i,j,k,now的方案数

细节再稍微注意一下就行了

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int N=110;
int n,m,T,l,r,x;
int a[N][N][2],f[2][N][N][N];
void add(int &x,int y){x=(x+y)%mod;}
int main() {
    scanf("%d",&T);
    while (T--){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) 
         for (int j=1;j<=4;j++) a[i][j][0]=mod,a[i][j][1]=0;
        for (int i=1;i<=m;i++) {
            scanf("%d%d%d",&l,&r,&x);
            a[r][x][0]=min(a[r][x][0],l);
            a[r][x][1]=max(a[r][x][1],l);
        }        
        memset(f[0],0,sizeof(f[0]));
        f[0][0][0][0]=1;
        for (int i=0;i<n;i++){
            for (int j=a[i+1][2][1];j<a[i+1][1][0]&&j<(i+1);j++)
                 for (int k=a[i+1][3][1];(k<a[i+1][2][0]&&k<j)||(k==0&&j==0);k++)
                    for (int p=a[i+1][4][1];(p<a[i+1][3][0]&&p<k)||(p==0&&k==0);p++) f[(i&1)^1][j][k][p]=0;
            for (int j=a[i][2][1];(j<a[i][1][0]&&j<i)||(j==0&&i==0);j++)
                 for (int k=a[i][3][1];(k<a[i][2][0]&&k<j)||(k==0&&j==0);k++)
                    for (int p=a[i][4][1];(p<a[i][3][0]&&p<k)||(p==0&&k==0);p++){
                            add(f[(i&1)^1][j][k][p],f[i&1][j][k][p]);
                            add(f[(i&1)^1][i][k][p],f[i&1][j][k][p]);
                            add(f[(i&1)^1][i][j][p],f[i&1][j][k][p]);
                            add(f[(i&1)^1][i][j][k],f[i&1][j][k][p]);
                        } 
        }
        int ans=0;
        for (int j=a[n][2][1];(j<a[n][1][0]&&j<n);j++)
            for (int k=a[n][3][1];(k<a[n][2][0]&&k<j)||(k==0&&j==0);k++)
                for (int p=a[n][4][1];(p<a[n][3][0]&&p<k)||(p==0&&k==0);p++)
                    add(ans,f[n&1][j][k][p]);
        printf("%d\n",ans);            
    }
}

1002:

[SCOI2016]幸运数字弱化版

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define pb(x) push_back(x)
using namespace std;
const int N=1e6+10;
const int D=30;
int f[N][D+10],a[N],pos[N][D+10];
vector<int>q[N];
int n,m,x,l,r,T,opt,lastans;
void add(int now,int x){
    int y=a[x];
    for (int i=D;i>=0;i--) 
        if ((y>>i)&1) {
            if (f[now][i]) y^=f[now][i]; else {
                f[now][i]=y; pos[now][i]=x; q[now].pb(x); break;
            }
        }
}
void init(){
    for (int i=1;i<=n;i++) {
        add(i,i);
        for (int j=0;j<q[i-1].size();j++) add(i,q[i-1][j]);
    }
}
void solve(int l,int r){
    int ans=0;
    for (int i=D;i>=0;i--) if ((!((ans>>i)&1))&&pos[r][i]>=l) ans^=f[r][i];
    printf("%d\n",ans);
    lastans=ans;
}
int main(){
    scanf("%d",&T);
    while (T--){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        init();
        lastans=0;
        for (int i=1;i<=m;i++){
            scanf("%d",&opt);
            if (opt==1) {
                scanf("%d",&x); x^=lastans; a[++n]=x;  
                add(n,n);
                for (int j=0;j<q[n-1].size();j++) add(n,q[n-1][j]);
            } else {
                scanf("%d%d",&l,&r); 
                l=(l^lastans)%n+1; r=(r^lastans)%n+1;
                if (l>r) swap(l,r);
                solve(l,r);
            }
        }
        for (int i=1;i<=n;i++) q[i].clear(),memset(f[i],0,sizeof(f[i]));
    }
}

1003:先咕着

1004:由于最后一辆车通过线时一定前面有一段连续的车挡着,枚举最前挡着的是哪辆车即可

话说我的写法为什么printf过不去???

#include<bits/stdc++.h>
#define ld long double
#define ll long long
using namespace std;
const int N=2e5+10;
ll l[N],s[N],v[N];
int n,t;
ll len;
ld ans;
int main(){
//    freopen("a.in","r",stdin);
//    freopen("a.out","w",stdout);
    while (~scanf("%d",&n)){
        for (int i=1;i<=n+1;i++) scanf("%lld",&l[i]);
        for (int i=1;i<=n+1;i++) scanf("%lld",&s[i]);
        for (int i=1;i<=n+1;i++) scanf("%lld",&v[i]);
        ans=0; len=0;
        for (int i=1;i<=n+1;i++) {
        ans=max(ans,(ld)((s[i]+len)*1.0/v[i]));  
        len+=l[i+1];
        }
        cout << fixed << setprecision(10) << ans << endl ;
    }
//    fclose(stdin);
//    fclose(stdout);
}

1005:建出最短路图后最小割即可

#pragma GCC optimize("2,Ofast,inline")
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define pb(x) push_back(x)
using namespace std;
const int N=1e4+10;
const int INF=1e17;
struct link{
    int u,to,w;
};
link edge[N<<2];
struct node{
    int v,u; ll len;
    node(int len1=0,int u1=0,int v1=0){len=len1,u=u1,v=v1;}
};
struct cmp{
    operator()(const node&a,const node&b){
        return a.len>b.len;
    }
};
int TI,n,m,x,y,c,k,head[N];
int dist[N];
template <typename T> void read(T &x) {
    int f = 0;
    register char c = getchar();
    while (c < '0' || c > '9') f |= (c == '-'), c = getchar();
    for (x = 0; c >= '0' && c <= '9'; c = getchar())
        x = (x << 3) + (x << 1) + (c ^ '0');
    if (f) x = -x;
}
namespace Maxflow {
    const int N = 1e4 + 7;
    const int M = 2e5 + 7;
    const int inf = 1e17;
    
    int E, V, S, T;
    int fir[N], cur[N], dis[N];
    int nex[M], arr[M], cap[M];

    inline void Add_Edge(int x, int y, int c) {
        nex[++E] = fir[x];
        fir[x] = E; arr[E] = y; cap[E] = c;
        nex[++E] = fir[y];
        fir[y] = E; arr[E] = x; cap[E] = 0;
    }

    int bfs() {
        static queue<int> Q;
        memset(dis, 0x3f, sizeof(int) * (V + 1));
        Q.push(S); dis[S] = 0;
        while (!Q.empty()) {
            int x = Q.front(); Q.pop();
            for (int i = fir[x]; i; i = nex[i]) {
                if (cap[i] && dis[arr[i]] > dis[x] + 1) {
                    dis[arr[i]] = dis[x] + 1;
                    Q.push(arr[i]);
                }
            }
        }
        return (dis[T] < inf);
    }

    int dfs(int x, int mf) {
        if (!mf || x == T) return mf;
        int ans = 0;
        for (int &i = cur[x]; i; i = nex[i]) {
            if (cap[i] && dis[arr[i]] == dis[x] + 1) {
                int del = dfs(arr[i], min(mf, cap[i]));
                ans += del; mf -= del;
                cap[i] -= del; cap[i ^ 1] += del;
                if (ans == mf) break;
            }
        }
        if (!ans) dis[x] = -1;
        return ans;
    }

    int dinic() {
        ll ans = 0;
        while (bfs())  {
            memcpy(cur, fir, sizeof(int) * (V + 1));
            ans += dfs(S, inf);
        }
        return ans;        
    }
}
using namespace Maxflow;
void add(int x,int y,int c){
    edge[k].u=y; edge[k].to=head[x]; edge[k].w=c; head[x]=k++;
}
void dij() {
    priority_queue<node,vector<node>,cmp>q; 
    for (int i=1;i<=n;i++) dist[i]=INF; dist[1]=0;
    for (int i=head[1];i!=-1;i=edge[i].to){
        int u=edge[i].u; q.push(node(edge[i].w,u,1));
    }
    while (!q.empty()){
        node v=q.top(); q.pop();
        if (dist[v.u]==INF) {
            dist[v.u]=v.len;
            Add_Edge(v.v,v.u,v.len-dist[v.v]);
            dist[v.u]=v.len;
            int now=v.u;
            for (int i=head[now];i!=-1;i=edge[i].to){
                int u=edge[i].u;
                q.push(node(dist[now]+edge[i].w,u,now));
            }
        } else if (dist[v.u]==v.len) {
            Add_Edge(v.v,v.u,v.len-dist[v.v]);
        }
    }
}
signed main(){
    scanf("%d",&TI);
    while (TI--){
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head)); k=0;
        E = 1;
        memset(fir, 0, sizeof fir);
        for (int i=1;i<=m;i++) {
            scanf("%d%d%d",&x,&y,&c);
            add(x,y,c); 
        }
        dij();
        S=1; T=n; V=n;
        printf("%lld\n",dinic());
    }
    return 0;
}

1006:后缀自动机优化dp即可

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
int rig[N<<1],Max[N<<1],ch[N<<1][26],fa[N<<1],f[N],pos[N];
char s[N];
ll dp[N];
ll w1,w2;
int len,sz,n_last;
void Make_Sam(int c,int id){
    int p=n_last,np=++sz; 
    rig[np]=id;
    Max[np]=Max[p]+1; n_last=np;
    for (;!ch[p][c]&&p;p=fa[p]) ch[p][c]=np;
    if (!p){fa[np]=1;return;}
    int q=ch[p][c];
    if (Max[q]==Max[p]+1) fa[np]=q; 
    else {
        int nq=++sz; fa[nq]=fa[q]; fa[q]=fa[np]=nq;
        Max[nq]=Max[p]+1; rig[nq]=rig[q];
        memcpy(ch[nq],ch[q],sizeof(ch[nq]));
        for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    }
}
void solve(int c,int id){
    dp[id]=dp[id-1]+w1;
    f[id]=f[id-1]; pos[id]=pos[id-1];
    for(;!ch[pos[id]][c]&&pos[id];pos[id]=fa[pos[id]]) f[id]=Max[fa[pos[id]]];
    if (!pos[id]) {
        pos[id]=1; return;
    }
    pos[id]=ch[pos[id]][c]; f[id]++;
    while ((rig[pos[id]]==id||rig[pos[id]]>=id-f[id]+1)&&f[id]) {
        f[id]--; if (f[id]==Max[fa[pos[id]]]) pos[id]=fa[pos[id]];
    }
    if (!f[id]) {pos[id]=1;return;}
    dp[id]=min(dp[id-f[id]]+w2,dp[id]);
}
int main() {
    while (~scanf("%s",s+1)){
        len=strlen(s+1);
        scanf("%lld%lld",&w1,&w2);
        sz=n_last=1; pos[0]=1;
        for (int i=1;i<=len;i++) Make_Sam(s[i]-'a',i),solve(s[i]-'a',i);
        printf("%lld\n",dp[len]);        
        for (int i=1;i<=sz;i++) memset(ch[i],0,sizeof(ch[i])),Max[i]=fa[i]=dp[i]=f[i]=pos[i]=0;
    }
}

1007:他咕了

1008:这题......

1009:贪心选最小的,暴力判合法性

#include<bits/stdc++.h>
#define ll long long
#define pb(x) push_back(x)
using namespace std;
const int N=1e5+10;
const int M=26;
int l[M],r[M];
int f[N][M];
char s[N]; 
int k,len;
vector<int>q[M];
bool pan(int now,int c){
    l[c]--; r[c]--; 
    int ans=0,sum=0;
    for (int i=0;i<M;i++)
     if (f[now+1][i]>=l[i]) ans+=min(f[now+1][i],r[i]),sum+=max(l[i],0); else {
    l[c]++; r[c]++;
    return 0;}
    l[c]++; r[c]++;
    return ans>=k-1&&k-1>=sum;
}
int main() {
//    freopen("a.in","r",stdin);
//    freopen("a.out","w",stdout);
    while (~scanf("%s",s+1)){
        scanf("%d",&k);
        len=strlen(s+1);
        for (int i=0;i<M;i++) scanf("%d%d",&l[i],&r[i]);
        memset(f[len+1],0,sizeof(f[len+1]));
        for (int i=len;i>=1;i--) {
            for (int j=0;j<M;j++) f[i][j]=f[i+1][j];
            f[i][s[i]-'a']++;
        }
        for (int i=len;i>=1;i--) q[s[i]-'a'].pb(i);
        int now=0;
        while (k){
            bool p=0;
            for (int i=0;i<M;i++) 
                while (!q[i].empty()&&q[i][q[i].size()-1]<=now) q[i].pop_back();
            for (int i=0;i<M;i++) 
                if (!q[i].empty()&&r[i]>0&&pan(q[i][q[i].size()-1],i)){
                    k--; now=q[i][q[i].size()-1]; p=1; l[i]--; r[i]--; putchar('a'+i); break;
                }
            if (!p)    break;
        } 
        if (k) puts("-1"); else puts("");
        for (int i=0;i<M;i++) q[i].clear();
    }
//    fclose(stdin);
//    fclose(stdout);
}

1010:他咕了

1011:他咕了

1012:对于这三种操作,考虑生成函数,然后乘起来牛顿二项式展开即可,做三遍NTT

#include<bits/stdc++.h>
#define ll long long
#define mk(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define cs const
using namespace std;
cs int g=3;
const int N=6e5+10;
const int mod=998244353;
typedef vector<int> poly;
int rev[N],inv[N],c[N],fac[N];
int s[5];
int n,m,len,d,x,k,T;
poly a;
int mul(int x,int y){return (ll)x*y%mod;}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y>=0?x-y:x-y+mod;}
int ksm(int x,int y){
    ll ans=1;
    for (;y;y>>=1,x=mul(x,x)) if (y&1) ans=mul(ans,x);
    return ans;
}
void in_it(){
    fac[0]=1;
    for (int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
    inv[0]=inv[1]=1;
    for (int i=2;i<N;i++) inv[i]=mul(inv[mod%i],(mod-mod/i));
    for (int i=1;i<N;i++) inv[i]=mul(inv[i],inv[i-1]);
} 
void init(int x){
    len=1,d=0;
    while (len<x) {len<<=1;d++;}
    for (int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(d-1));
}
int BSGS(int X,int Y){
    int now=floor(sqrt(mod));
    int s=ksm(X,now);
    map<int,int>mp;
    int t=1;
    int sum=Y;
    for (int i=0;i<now;i++){
        mp[sum]=i; sum=mul(sum,X);
    }
    int s1=1;
    for (int i=0;i<mod;i+=now){
        s1=mul(s1,s);
        if (mp[s1]) return i+now-mp[s1];
    }
}
int lalala(int x){
    int now=BSGS(g,x);
    return ksm(g,now/2);
}
void out(poly a){
    for (int i=0;i<a.size();i++) printf("%d ",a[i]);
    puts("\n");
}
inline poly NTT(poly a,int t) {
    for (int i=0;i<a.size();i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
    for (int i=1;i<a.size();i<<=1) {
      int s=(i<<1);
      int wn=ksm(g,(mod-1)/s);
      if (t==-1) wn=ksm(wn,mod-2);
      for (int j=0;j<a.size();j+=s) {
          int w=1;
          for (int k=j;k<j+i;k++) {
               int x=a[k],y=mul(a[k+i],w);
               a[k]=add(x,y); a[k+i]=dec(x,y);
               w=mul(w,wn);
         }
      }
    }
    if (t==-1){
        ll w=ksm(a.size(),mod-2);
        for (int i=0;i<a.size();i++) a[i]=mul(a[i],w);
    }
    return a;
}
inline poly get_down(poly a){
    for (int i=0;i<a.size()-1;i++) a[i]=mul(a[i+1],i+1);
    a.pop_back();
    return a;
}
inline poly get_up(poly a){
    a.push_back(0);
    for (int i=a.size()-1;i>0;i--) a[i]=mul(a[i-1],inv[i]);
    a[0]=0;
    return a; 
}
inline poly operator +(poly a,poly b){
    a.resize(max(a.size(),b.size()));
    b.resize(max(a.size(),b.size()));
    for (int i=0;i<a.size();i++) a[i]=add(a[i],b[i]);
    return a; 
}
inline poly operator -(poly a,poly b){
    a.resize(max(a.size(),b.size()));
    b.resize(max(a.size(),b.size()));
    for (int i=0;i<a.size();i++) a[i]=dec(a[i],b[i]);
    return a;
}
inline poly operator *(poly a,int x){
    for (int i=0;i<a.size();i++) a[i]=mul(a[i],x);
    return a;
}
inline poly operator *(poly a,poly b){
    int n=a.size(),m=b.size(); 
    init(n+m-1);
    a.resize(len);
    b.resize(len);
    a=NTT(a,1); b=NTT(b,1);
    for (int i=0;i<a.size();i++) a[i]=mul(a[i],b[i]);
    a=NTT(a,-1);
    a.resize(n+m-1);
    return a;
}
inline poly get_inv(poly a){
    poly b,d;
    b.pb(ksm(a[0],mod-2)); d.pb(a[0]);
    int now=1;
    while (now<a.size()) {
        now<<=1; 
        poly c=b;
        c=c*c;
        for (int i=(now>>1);i<now&&i<a.size();i++) d.pb(a[i]);
        c=c*d;c.resize(now); 
        b=b*2;  b=b-c;
    }
    b.resize(a.size());
    return b;
}
inline poly ln(poly a){poly c=get_up(get_inv(a)*get_down(a));c.resize(a.size());return c;}
inline poly exp(poly a){
    poly b,d;
    b.pb(1); d.pb(a[0]);
    int now=1;
    while (now<a.size()){
          now<<=1;
           for (int i=(now>>1);i<now&&i<a.size();i++) d.pb(a[i]);
           poly c=b;
           c.resize(now);
           c=ln(c)-d;
           for (int i=0;i<c.size();i++) c[i]=(mod-c[i])%mod;
           c[0]=add(c[0],1); 
           b=b*c; b.resize(now); 
    }    
    b.resize(a.size());
    return b;
}
/*
inline poly ksm(poly a,int k){return exp(ln(a)*k);}
inline poly Sqrt(poly a){
    poly b,d;
    b.pb(lalala(a[0])); d.pb(a[0]);
    b[0]=min(b[0],mod-b[0]);
    int now=1;
    while (now<a.size()){
        now<<=1; poly c=b;
        for (int i=(now>>1);i<now&&i<a.size();i++) d.pb(a[i]);
        c.resize(now);
        c=get_inv(c);
        c=c*d;c.resize(now);
        b=b+c;
        for (int i=0;i<now;i++) b[i]=mul(b[i],inv[2]);
    }
    b.resize(a.size());
    return b;
}
*/
int C(int x,int y){
    if (x<y||x<0||y<0) return 0;
    return mul(mul(fac[x],inv[y]),inv[x-y]);
}
void solve(){
    for (int i=1;i<=3;i++){
        poly b; 
        c[0]=1;
        for (int j=1;j<=n;j++) if (j%i==0) c[j]=C(s[i]+j/i-1,j/i); else c[j]=0;
        for (int j=0;j<=n;j++) b.pb(c[j]);
//        out(b);
        a=a*b; a.resize(n+1);
    }
//    out(a);
    ll ans=0;
    for (int i=1;i<=n;i++) ans^=((ll)a[i]*i);
    printf("%lld\n",ans);
}
int main(){
    scanf("%d",&T);
    in_it();
//    cout << fac[3] << endl;
    while (T--){
        scanf("%d%d",&n,&m);
        s[1]=s[2]=s[3]=0;
        a.pb(0);
        for (int i=1;i<=n;i++) scanf("%d",&x),a.pb(x);
        for (int i=1;i<=m;i++) {scanf("%d",&x); s[x]++;}
        solve();
        a.clear();
    }
}

1013:他咕了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值