2020 Multi-University Training Contest 3

代码不想写就口胡了

1001.
用 歌唱王国 的结论
$E(A)=\sum_{i=1}^{len} a_{i}*m^i,\ a_{i}=is\_border(i)$
回文串border就是回文自动机的fail
直接上回文自动机比较字典序即可

1002.

1003.
直接离线考虑每一位的贡献
用个dfs序维护线段 树去掉u,v是祖先儿子的情况就行
$O(20*n*logn)$

1004.
$sum_{i}=(sum_{i-1}+a[i])\%mod$
$f_{i}=max(f_{i-1},max\{f_{j}|sum(j)=sum(i)\}+1)$


1005.
没看

1006.
数位dp
写了一个小时,真实自闭

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long s64;

inline int read() {
    int f=1,sum=0;
    char x=getchar();
    for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
    for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
    return f*sum;
}



int len;
int wei[20];
int cnt[10];

void divid_(s64 n) {
    len=0;
    while (n) {
        wei[++len]=n%10;
        n/=10;
    }
}


s64 f[2][20];
s64 C[20][20];


s64 get_C(int x,int y) {
    return C[x][y];
}


s64 dp(int x,int d,bool is_zero) {
    s64 ans=0;
    if(d==0) {
       // cout<<"-_-x:"<<x<<endl;
        rep(i,0,x) {

           // i=2;
            memset(f,0,sizeof(f));
            int opt=0;
            f[0][i]=get_C(x-is_zero,i);
            //cout<<i<<" "<<f[0][i]<<endl;

            rep(j,1,9) {
                opt^=1;
                memset(f[opt],0,sizeof(f[opt]));
                //cout<<j<<" "<<i+cnt[d]-1-cnt[j]<<" "<<x-cnt[j]<<endl;
                rep(u,0,i+cnt[d]-1-cnt[j]) rep(k,0,x-u) f[opt][u+k]+=f[opt^1][k]*get_C(x-k,u);
            }
            ans+=f[opt][x]; 
            //cout<<"ans:"<<ans<<endl;
            //while (1);
        }
    }
    else {
        rep(i,0,x) {
            memset(f,0,sizeof(f));
            int opt=0;
            rep(j,0,i+cnt[d]-1-cnt[0]) f[0][j]=get_C(x-is_zero,j);

            rep(j,1,9) {
                if(d==j) {
                    opt^=1;
                    memset(f[opt],0,sizeof(f[opt]));
                    rep(k,i,x) f[opt][k]=f[opt^1][k-i]*get_C(x-k+i,i);
                    continue;
                }
                
                opt^=1;
                memset(f[opt],0,sizeof(f[opt]));
                rep(u,0,i+cnt[d]-1-cnt[j]) rep(k,0,x-u) f[opt][u+k]+=f[opt^1][k]*get_C(x-k,u);
            }
            ans+=f[opt][x]; 
        }
    }
    return ans;
}


bool check(int d) {
    int aa[10]={0};
    rep(i,1,len) ++aa[wei[i]];
    rep(i,0,9) if(i!=d&&aa[i]>=aa[d]) return 0;
    return 1; 
}

s64 calc(s64 n,int d) {
    divid_(n);

    memset(cnt,0,sizeof(cnt));

    s64 ans=0;
    rep(i,1,len-1) ans+=dp(i,d,1);
    per(i,len,1) {
        //cout<<"-_-"<<ans<<endl;
        rep(j,i==len,wei[i]-1) {

            ++cnt[j];
            ans+=dp(i-1,d,0);
        //cout<<"-_-"<<i<<" "<<j<<" "<<dp(i-1,d,0)<<endl;
            --cnt[j];
        }
        ++cnt[wei[i]];
    }
    if(check(d)) ++ans;
    return ans;
}

signed main () {
    //freopen("a.txt","r",stdin);
    //freopen("a.out","w",stdout);
    int test_=read();

    rep(i,0,19) C[i][0]=1;
    rep(i,1,19) rep(j,1,19) C[i][j]=C[i-1][j]+C[i-1][j-1];

    while (test_--) {
        s64 l,r;
        int d;
        cin>>l>>r>>d;
        //cout<<calc(l-1,d)<<endl;
       // cout<<calc(l-1,d)<<" "<<calc(r,d)<<endl;
        cout<<calc(r,d)-calc(l-1,d)<<endl;
    }
}
1006

1007.

脑残题,不知道为什么边权是随机的

搞了半天自己取的是min还能过样例

性质就是最短路径很短,然后直接搜就行了

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long s64;

inline int read() {
    int f=1,sum=0;
    char x=getchar();
    for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
    for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
    return f*sum;
}


const int M=1e2+5;
int n,m;
int a[M][M];
int ans;
bool can[M][M][M];


bool vis[M][M];

int dis[M],pre[M];
bool inq_[M];

void floyd(int x) {
    memset(can[x],0,sizeof(can[x]));


    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    queue<int> q;
    q.push(1);
    while (!q.empty()) {
        int r=q.front();
        q.pop();
        inq_[r]=0;
        rep(i,1,n) if(!vis[r][i]&&dis[i]>dis[r]+a[r][i]) {
            dis[i]=dis[r]+a[r][i];
            pre[i]=r;

            if(!inq_[i]) inq_[i]=1,q.push(i);
        }
    }

    int now=n;
    while (now!=1) {
        can[x][pre[now]][now]=can[x][now][pre[now]]=1;
        now=pre[now];
    }
}

void calc() {
    floyd(10);
    ans=max(ans,dis[n]);
}

void dfs(int x) {
    if(x==m+1) return calc(),void();
    floyd(x);

    rep(i,1,n) rep(j,i+1,n) if(can[x][i][j]) {
        vis[i][j]=vis[j][i]=1;
        dfs(x+1);
        vis[i][j]=vis[j][i]=0;
    }
}

signed main () {
    //freopen("a.txt","r",stdin);
    //freopen("a.out","w",stdout);
    int test_=read();

    while (test_--) {
        n=read(),m=read();
        //cout<<n<<" "<<m<<endl;
        rep(i,1,n) rep(j,i+1,n) {
            int x=read(),y=read();
            a[x][y]=a[y][x]=read();
        }
        ans=0;
        memset(can,0,sizeof(can));

        dfs(1);
        cout<<ans<<endl;
    }
}
1007

1008.

关键就是把反射问题变成无线个三角形放在平面上的情况

二分答案,判断能相交多少次就行,直接用长度除以间距即可

1009.

好像比较简单,没看 

1010.

1011.

猜你喜欢

转载自www.cnblogs.com/asd123www/p/13393876.html