1. 程式人生 > 實用技巧 >2020 Multi-University Training Contest 3

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.