CXJY-Day 8

Author Avatar
Axell 8月 05, 2019
  • 在其它设备中阅读本文章

题面

T1

KMP,求出每个前缀匹配的最大后缀,即Next数组,然后可以发现以i->Next[i]建立一棵树,树上的若干节点的所有lca就是符合条件的pq

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

struct node{
    int Next,y;
}Pth[1000005];
int cnt,head[1000005];
void add(int x,int y){
    cnt++;
    Pth[cnt]={head[x],y};
    head[x]=cnt;
}
int n,k,Next[1000005],siz[1000005];
char s[1000005];
ll A,ans[1000005],fac[1000005],mod=998244353;
ll power(ll x,ll y){
    ll ret=1;
    while (y){
        if (y&1) ret=ret*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ret;
}
ll C(ll x,ll y){
    return fac[x]*power(fac[y],mod-2)%mod*power(fac[x-y],mod-2)%mod;
}
void dfs(int x,int dep,int prv){
    siz[x]=1;
    for (int i=head[x];i;i=Pth[i].Next){
        int y=Pth[i].y;
        if (y==prv) continue;
        dfs(y,dep+1,x);
        siz[x]+=siz[y];
    }
    if (siz[x]>=k) ans[x]+=C(siz[x],k);
    ans[x]%=mod;
    if (ans<0) ans[x]+=mod;
    A+=ans[x]*(dep+dep+1)%mod;
    A%=mod;
}

int main(){
    freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    cin>>k;
    scanf("%s",s+1);
    n=strlen(s+1);
    fac[0]=1;
    for (int i=1;i<=n+1;++i) fac[i]=fac[i-1]*i%mod;
    for (int i=2,j=0;i<=n;++i){
        while (j>0 && s[j+1]!=s[i]) j=Next[j];
        if (s[j+1]==s[i]) j++;
        Next[i]=j;
    }
    for (int i=1;i<=n;++i){
        add(Next[i],i);
    }
    dfs(0,0,-1);
    cout<<A<<endl;
    return 0;
}

T2

TODO

#include<bits/stdc++.h>

using namespace std;

const int MX=2005,CHARC=257,MXL=8000000;

const int dx[4]={0,-1,0,1},dy[4]={1,0,-1,0};
const char op[4]={'R','U','L','D'};
int dir[CHARC];
const char ch[4][2]={ {'<','>'},{'u','n'},{'>','<'},{'n','u'}};

int n,m,RINGC;
char a[MX][MX],b[MX][MX];
bool vis[MX][MX];
char ans[MXL+5];int ansc;

void ini(){
    dir['<']=0,dir['>']=2,dir['u']=1,dir['n']=3;
}
void move(int di,int &x,int &y){
    ans[ansc++]=op[di];
    int xt=x+dx[di],yt=y+dy[di];
    if(xt<0||xt>=n||yt<0||yt>=m)return;
    int xx=xt+dx[dir[a[xt][yt]]],yy=yt+dy[dir[a[xt][yt]]];
    a[x][y]=ch[di][0],a[xt][yt]=ch[di][1];
    x=xx,y=yy;
    a[x][y]='o';
}
void work0(int &x,int &y){ // the augment path between two 'o's
    while(b[x][y]!='o'){
        move(dir[b[x][y]],x,y);
    }
}
void reducering(int &x,int &y,int di){
    int x0=x,y0=y;
    move(di,x,y);
    while(x!=x0||y!=y0){
        move(dir[b[x][y]],x,y);
    }
}
void dfs(int &x,int &y){
    vis[x][y]=true;
    for(int i=0;i<4;i++){
        int xt=x+dx[i],yt=y+dy[i];
        if(xt<0||xt>=n||yt<0||yt>=m||a[xt][yt]=='#')continue;
        if(vis[xt][yt])continue;
        if(a[xt][yt]!=b[xt][yt]){ // found a ring
            ++RINGC;
            reducering(x,y,i);
        }
        vis[xt][yt]=true;
        int td=dir[a[xt][yt]];
        move(i,x,y);
        dfs(x,y);
        move(td^2,x,y);
    }
}
bool check(){
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(a[i][j]!=b[i][j])
                return false;
    return true;
}
void solve(){
    int x,y;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(a[i][j]=='o')x=i,y=j;
    work0(x,y);
    dfs(x,y);
    if(check())cout<<ans<<endl;
    else cout<<"I"<<endl;
}
int main(){
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    ios::sync_with_stdio(false);
    ini();
    cin>>n>>m;
    for(int i=0;i<n;i++)
        cin>>a[i];
    for(int i=0;i<n;i++)
        cin>>b[i];
    solve();
    return 0;
}

T3

TODO

#include <cstdio>
#include <iostream>
#include <cstring>
#include <tr1/unordered_map>
#include <cmath>
#include <algorithm>
//#define int long long
using namespace std;
using namespace tr1;
const int maxn = 200000 + 10, mod = 998244353;
void R(int &x) {
    x = 0;
    char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + c - '0';
        c = getchar();
    }
}
int Prime[maxn], vis[maxn], Z[maxn], V[maxn], G[maxn], Inv6, Cnt[maxn], n, m, q, K[maxn], Lim;
int qpow(int x, int y) {
    int ans = 1;
    while (y) {
        if (y & 1)
            ans = 1ll * x * ans % mod;
        x = 1ll * x * x % mod;
        y >>= 1;
    }
    return ans;
}
int Sum(int x) { return 1ll * x * (x + 1) % mod * ((2 * x + 1) % mod) % mod * Inv6 % mod; }
int add(int x, int y) {
    x += y;
    if (x >= mod)
        x -= mod;
    return x;
}
void Get() {
    for (int i = 2; i < maxn; i++) {
        if (!vis[i])
            Prime[++Prime[0]] = i;
        for (int j = 1; j <= Prime[0]; j++) {
            if (1ll * i * Prime[j] >= maxn)
                break;
            vis[i * Prime[j]] = 1;
            if (i % Prime[j] == 0)
                break;
        }
    }
}
void work(int x) {
    if (Z[0] == 10)
        return;
    int k = sqrt(x);
    for (int i = 1; i <= Z[0]; i++)
        if (x % Z[i] == 0) {
            while (x % Z[i] == 0) x /= Z[i];
        }
    for (int i = 1; Prime[i] <= k; i++) {
        if (x == 1)
            break;
        if (x % Prime[i] == 0) {
            Z[++Z[0]] = Prime[i];
            while (x % Prime[i] == 0) x /= Prime[i];
        }
    }
    if (x != 1)
        Z[++Z[0]] = x;
}
void Calc() {
    Lim = sqrt(n);
    for (int i = 1; i <= n; i = V[V[0]] + 1) {
        V[++V[0]] = n / (n / i);
        G[V[0]] = Sum(V[V[0]]);
    }
    for (int w = 1; w <= Z[0]; w++) {
        int p = Z[w], p2 = 1ll * p * p % mod;
        for (int i = V[0]; V[i] >= p; i--) {
            int to = V[i] / p;
            if (to > Lim)
                to = V[0] - n / to + 1;
            G[i] = (G[i] - 1ll * G[to] * p2 % mod + mod) % mod;
        }
    }
}
unordered_map<int, int> P;
void dfs(int w, int data) {
    if (w == Z[0] + 1) {
        Cnt[++Cnt[0]] = data;
        if (!P.count(data))
            P[data] = 0;
        return;
    }
    dfs(w + 1, data);
    while (1ll * data * Z[w] <= n) {
        data *= Z[w];
        dfs(w + 1, data);
    }
}
signed main() {
    freopen("C.in","r",stdin);
    freopen("C.out","w",stdout);
    Get();
    Inv6 = qpow(6, mod - 2);
    R(n);
    R(m);
    R(q);
    for (int i = 1; i <= m; i++) {
        int p, x;
        R(p);
        R(x);
        work(p);
        if (!P.count(p))
            P[p] = 0;
        P[p] = (P[p] + x) % mod;
    }
    while (q--) {
        int x;
        R(x);
        K[++K[0]] = x;
        work(x);
    }
    sort(Z + 1, Z + 1 + Z[0]);
    dfs(1, 1);
    sort(Cnt + 1, Cnt + 1 + Cnt[0]);
    for (int w = 1; w <= Z[0]; w++) {
        int p = Z[w];
        for (int i = 1; i <= Cnt[0]; i++) {
            if (Cnt[i] % p != 0)
                continue;
            int tmp = Cnt[i] / p;
            while (!P.count(tmp)) tmp /= p;
            P[Cnt[i]] = add(P[Cnt[i]], 1ll * (Cnt[i] / tmp) * P[tmp] % mod) % mod;
        }
    }
    Calc();
    for (int i = 1; i <= Cnt[0]; i++) {
        int to = n / Cnt[i];
        if (to > Lim)
            to = V[0] - n / to + 1;
        P[Cnt[i]] = 1ll * P[Cnt[i]] * G[to] % mod;
    }
    for (int w = 1; w <= Z[0]; w++) {
        int p = Z[w];
        for (int i = Cnt[0]; i >= 1; i--) {
            if (1ll * Cnt[i] * p > n)
                continue;
            int tmp = Cnt[i] * p;
            while (!P.count(tmp) && 1ll * tmp * p <= n) tmp *= p;
            if (P.count(tmp))
                P[Cnt[i]] = add(P[Cnt[i]], 1ll * P[tmp] * (tmp / Cnt[i]) % mod);
        }
    }
    for (int i = 1; i <= K[0]; i++) printf("%d\n", P[K[i]]);
}

匹配

匹配的任意两条边没有公共顶点
TODO:二分图最大匹配

生成树

BZOJ 2654
http://uoj.ac/problem/3

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

本文链接:https://hs-blog.axell.top/archives/cxjy-day-8/