The 2024 ICPC Asia Hong Kong Regional Contest

题解:

https://files.cnblogs.com/files/clrs97/2024_Hong_Kong_Tutorial.pdf

 

Code:

A. General Symmetry

// floating point errors
#pragma GCC optimize("Ofast,unroll-loops")
 
// safe
// #pragma GCC optimize("O3,unroll-loops")
 
// doesn't work in yandex
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
 
// doesn't work in some judges
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt,tune=native")
 
// safe
// #pragma GCC target("sse4.2,bmi,bmi2,lzcnt,popcnt")
#include<iostream>
#include<bitset>
#include<algorithm>
using namespace std;
const int N=200005,V=1000,K=5;
int n,m,k,i,l,r,a[N];
struct BIT{
  unsigned long long v[(N>>6)+1];
  bool get(int x)const{return v[x>>6]>>(x&63)&1;}
  void set(int x){v[x>>6]|=1ULL<<(x&63);}
  void operator^=(const BIT&o){for(int i=0;i<=m;i++)v[i]^=o.v[i];}
  void operator=(const BIT&o){for(int i=0;i<=m;i++)v[i]=o.v[i];}
  void shiftand(const BIT&o){
    for(int i=0;i<m;i++)v[i]=((v[i]>>1)+((v[i+1]&1)<<63))&o.v[i];
    v[m]=(v[m]>>1)&o.v[m];
  }
}occ[V+1],mask[V+1],f,save[(N>>K)+1];
inline int myabs(int x){return x>0?x:-x;}
inline bool check(int l,int r){return myabs(a[l]-a[r])<=k;}
inline int ask(int A,int B){
  if(!check(A,B))return 0;
  int l=((B-1)>>K)+1,r=n>>K,mid,t=0;
  while(l<=r){
    mid=(l+r)>>1;
    int d=(mid<<K)-B;
    if(A-d>=1&&save[mid].get(A-d))l=mid+1,t=d;else r=mid-1;
  }
  A-=t,B+=t;
  while(A>1&&B<n&&check(A-1,B+1))A--,B++;
  return B-A+1;
}
int main(){
  ios_base::sync_with_stdio(0);cin.tie(0);
  cin>>n>>k;
  m=n>>6;
  for(i=1;i<=n;i++)cin>>a[i];
  for(i=1;i<=n;i++)occ[a[i]].set(i);
  for(i=2;i<=V;i++)occ[i]^=occ[i-1];
  for(i=1;i<=V;i++){
    l=max(i-k,1);
    r=min(i+k,V);
    mask[i]=occ[r];
    mask[i]^=occ[l-1];
  }
  for(i=1;i<=n;i++){
    m=i>>6;
    f.shiftand(mask[a[i]]);
    f.set(i);
    if(i>1&&check(i-1,i))f.set(i-1);
    if(!(i&((1<<K)-1)))save[i>>K]=f;
  }
  for(i=1;i<=n;i++){
    cout<<ask(i,i);
    if(i<n)cout<<" ";else cout<<"\n";
  }
  for(i=1;i<n;i++){
    cout<<ask(i,i+1);
    if(i+1<n)cout<<" ";else cout<<"\n";
  }
}

  

B. Defeat the Enemies

#include <bits/stdc++.h>
using namespace std;
int n , m;
int a[500005] , b[500005];
const int mod = 998244353;
typedef long long ll;
void upd(int &x,int y) {
    ((x += y) >= mod ? (x -= mod) : 0) ;
}
int c[105] , k;
void solv() {
    cin >> n >> m;
    int mx = 0;
    for(int i = 1;i <= n;i++) cin >> a[i]; 
    for(int i = 1;i <= n;i++) cin >> b[i]; 
    cin >> k;
    for(int i = 1;i <= k;i++) cin >> c[i];
 
    for(int i = 1;i <= n;i++) mx = max(mx , a[i] + b[i]) ;
    vector<int> h(mx + k*2 + 1 , 1e9) ;
    for(int i = 1;i <= n;i++) {
        int x = mx - (a[i] + b[i]) ;
        h[b[i] - 1] = min(h[b[i] - 1] , b[i] + x) ;
    }
    for(int i = mx + k*2 - 1; i >= 0;i--) h[i] = min(h[i] , h[i + 1]) ;
 
    vector<ll> f(mx + k*2 + 1) ;
    vector<int> g(mx + k*2 + 1) ;
    ll ans = 1e18;
    int cnt = 0;
 
    for(int d = 0 ; d <= k * 2 - 2 ; d++) {
        for(auto &x : f) x = 1e18;
        for(auto &x : g) x = 0;
        f[0] = 0; g[0] = 1;
        for(int i = 0 ;i < mx + d ; i++) {
            for(int j = 1 ; j <= k && i + j <= mx + d && i + j <= h[i] + d ; j++) {
                if(f[i + j] > f[i] + c[j]) {
                    f[i + j] = f[i] + c[j] ;
                    g[i + j] = g[i] ;
                }
                else if(f[i + j] == f[i] + c[j]) {
                    upd(g[i + j] , g[i]) ;
                }
            }
        }
        if(f[mx + d] < ans) {
            ans = f[mx + d]; cnt = g[mx + d] ;
        }
        else if(f[mx + d] == ans) upd(cnt , g[mx + d]) ;
    }
    cout << ans <<' ' << cnt << '\n' ;
    return ;
}
int main() {
    ios::sync_with_stdio(false) ; cin.tie(0) ;
    int t ; cin >> t;
    while(t--) solv() ;
}

  

C. The Story of Emperor Bie

#include <bits/stdc++.h>
using namespace std;
int p[500005];
int n ;
void solv() {
    cin >> n;
    for(int i = 1;i <= n;i++) cin >> p[i] ;
    int mx = *max_element(p + 1 , p + n + 1) ;
    for(int i = 1;i <= n;i++) {
        if(p[i] == mx) cout << i <<' ' ;
    }
    cout << '\n';
}
int main() {
    ios::sync_with_stdio(false) ; cin.tie(0) ;
    int t ; cin >> t;
    while(t--) solv() ;
}

  

D. Master of Both VI

#include<bits/stdc++.h>
using namespace std;
 
using ll=int;
 
const int N=5e5+1e3+7,Q=3e5+1e3+7;
 
int n,q,fa[N];
 
vector<int> g[N];
 
struct Mat {
    ll f00,f01,f10,f11;
};
 
struct Vec {
    ll f0,f1;
    ll gmn(){return min(f0,f1);}
};
 
Vec operator *(const Mat &a,const Vec &b)
{
    return {min(a.f00+b.f0,a.f01+b.f1),min(a.f10+b.f0,a.f11+b.f1)};
}
 
Mat operator *(const Mat &a,const Mat &b)
{
    return {min(a.f00+b.f00,a.f01+b.f10),
            min(a.f00+b.f01,a.f01+b.f11),
            min(a.f10+b.f00,a.f11+b.f10),
            min(a.f10+b.f01,a.f11+b.f11)};
}
 
struct T {
    int ls,rs,cnt;
    Mat v;
}t[Q*2*19];
 
int st[20][N],dfn[N],dc;
 
void dfs(int x,int f)
{
    fa[x]=f;
    st[0][dc]=f;
    dfn[x]=++dc;
    for(auto v:g[x])
    {
        if(v==f)
            continue;
        dfs(v,x);
    }
}
 
int mn(int x,int y)
{
    return dfn[x]<dfn[y]?x:y;
}
 
int lca(int x,int y)
{
    if(dfn[x]>dfn[y])
        swap(x,y);
    int k=__lg(dfn[y]-dfn[x]);
    return x!=y?mn(st[k][dfn[x]],st[k][dfn[y]-(1<<k)]):x;
}
 
vector<int> add[N],qr[N];
 
int rt[N],cnt;
 
ll w[Q];
 
void update(int x)
{
    t[x].cnt=t[t[x].ls].cnt+t[t[x].rs].cnt;
    if(!t[x].cnt)
        return;
    else if(!t[t[x].ls].cnt)
        t[x].v=t[t[x].rs].v;
    else if(!t[t[x].rs].cnt)
        t[x].v=t[t[x].ls].v;
    else
        t[x].v=t[t[x].ls].v*t[t[x].rs].v;
}
 
Mat Z={0,(ll)1e9,(ll)1e9,0};
 
void ins(int &x,int l,int r,int p,int v)
{
    if(!x)
        x=++cnt;
    if(l==r)
    {
        if(v>0)
        {
            t[x].cnt=1;
            t[x].v={w[l]*2,w[l],w[l]*2,w[l]*2};
        }
        else
        {
            t[x].cnt=0;
            t[x].v=Z;
        }
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid)
        ins(t[x].ls,l,mid,p,v);
    else
        ins(t[x].rs,mid+1,r,p,v);
    update(x);
}
 
int merge(int x,int y,int l,int r)
{
    if(!x||!y)
        return x+y;
    if(l==r)
        return t[x].cnt?x:y;
    int mid=(l+r)>>1;
    t[x].ls=merge(t[x].ls,t[y].ls,l,mid);
    t[x].rs=merge(t[x].rs,t[y].rs,mid+1,r);
    update(x);
    return x;
}
 
int fd;
 
int qry(int x,int l,int r,int p,Vec &u,ll h)
{
    if(r<=p)
    {
        auto ru=t[x].v*u;
        if(ru.gmn()<h)
        {
            u=ru;
            return t[x].cnt;
        }
    }
    if(l==r)
    {
        fd=1;
        return 0;
    }
    int mid=(l+r)>>1;
    int ret=0;
    if(p>mid&&t[t[x].rs].cnt)
        ret=qry(t[x].rs,mid+1,r,p,u,h);
    if(!t[t[x].ls].cnt||fd)
        return ret;
    ret+=qry(t[x].ls,l,mid,p,u,h);
    return ret;
}
 
int ans[Q];
 
void getans(int x)
{
    for(auto v:g[x])
    {
        if(v==fa[x])
            continue;
        getans(v);
        rt[x]=merge(rt[x],rt[v],1,q);
    }
    for(auto id:add[x])
        ins(rt[x],1,q,abs(id),id);
    for(auto id:qr[x])
    {
        Vec u={0,0};
        fd=0;
        ans[id]=qry(rt[x],1,q,id,u,w[id]*2);
    }
}
 
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    t[0].v=Z;
    cin>>n>>q;
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    for(int i=1;i<20;i++)
        for(int j=1;j+(1<<i)-1<n;j++)
            st[i][j]=mn(st[i-1][j],st[i-1][j+(1<<i-1)]);
    memset(ans,-1,sizeof(ans));
    for(int i=1;i<=q;i++)
    {
        string op;
        cin>>op;
        if(op[0]=='A')
        {
            int u,v;
            cin>>u>>v>>w[i];
            int p=lca(u,v);
            add[u].push_back(i);
            add[v].push_back(i);
            add[fa[p]].push_back(-i);
        }
        else
        {
            int x;
            cin>>x>>w[i];
            qr[x].push_back(i);
        }
    }
    getans(1);
    for(int i=1;i<=q;i++)
        if(ans[i]!=-1)
            cout<<ans[i]<<"\n";
}

  

E. Concave Hull

#include<bits/stdc++.h>
using namespace std;
const int N=2505;
typedef long long ll;
const int mod=1e9+7;
int n,ans;
bool on[N];
struct Point{
    int x,y,id;
    Point(int _x=0,int _y=0,int _id=-1):x(_x),y(_y),id(_id){}
    friend Point operator - (const Point &a,const Point &b){
        return Point(a.x-b.x,a.y-b.y);
    }
    friend Point operator + (const Point &a,const Point &b){
        return Point(a.x+b.x,a.y+b.y);
    }
    friend ll operator % (const Point &a,const Point &b){
        return 1LL*a.x*b.y-1LL*a.y*b.x;
    }
    friend bool operator < (const Point &a,const Point &b){
        return a.y==b.y?a.x<b.x:a.y<b.y;
    }
    inline ll len2(){
        return 1LL*x*x+1LL*y*y;
    }
    inline int Quad(){
        return y>0||(y==0&&x>0);
    }
};
typedef vector<Point> poly;
inline bool Left(Point a,Point b){
    return b%a>0;
}
poly A;
int Area(poly A){
    int m=A.size();
    int tot=0;
    for(int i=0;i<m;++i){
        tot=(tot+(A[i]%A[(i+1)%m]))%mod;
    }
    tot=(tot+mod)%mod;
    return tot;
}
void calc(poly B){
    sort(B.begin(),B.end(),[&](Point a,Point b){
        return a.Quad()^b.Quad()?a.Quad()>b.Quad():Left(b,a);
    });
    for(int i=0;i<(int)B.size();++i){
        if(on[B[i].id]){
            rotate(B.begin(),B.begin()+i,B.end());
            break;
        }
    }
    B.push_back(B[0]);
    int cnt=0;
    poly st;
    ll now=0;
    for(auto &p:B){
        while(st.size()>1&&Left(st.back()-st[st.size()-2],p-st[st.size()-2])){
            now=(now-(st[st.size()-2]%st.back()))%mod;
            st.pop_back();
        }
        if(st.size()>0){
            now=(now+(st.back()%p))%mod;
        }
        st.push_back(p);
        ++cnt;
        if(on[p.id]){
            if(st.size()>1){
                ans=(ans+cnt*((st[st.size()-2]%st.back())%mod))%mod;
            }
            cnt=0;
            now=0;
        }
        ans=(ans-now)%mod;
    }
    reverse(B.begin(),B.end());
    now=0;
    for(auto &p:B){
        while(st.size()>1&&Left(p-st[st.size()-2],st.back()-st[st.size()-2])){
            now=(now-(st.back()%st[st.size()-2]))%mod;
            st.pop_back();
        }
        if(st.size()>0){
            now=(now+(p%st.back()))%mod;
        }
        st.push_back(p);
        if(on[p.id]){
            now=0;
        }
        ans=(ans-now)%mod;
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    A.resize(n);
    for(int i=0;i<n;++i){
        cin>>A[i].x>>A[i].y;
        A[i].id=i;
    }
    Point LTL=*min_element(A.begin(),A.end());
    sort(A.begin(),A.end(),[&](Point a,Point b){
        a=a-LTL;
        b=b-LTL;
        if((a%b)==0)return a.len2()<b.len2();
        return Left(b,a);
    });
    poly st;
    for(auto &p:A){
        while(st.size()>1&&Left(st.back()-st[st.size()-2],p-st[st.size()-2])){
            st.pop_back();
        }
        st.push_back(p);
    }
    for(auto &p:st){
        on[p.id]=1;
    }
    for(auto &t:A){
        if(on[t.id])continue;
        poly B;
        for(auto &p:A){
            if(p.id!=t.id){
                B.push_back(p-t);
                B.back().id=p.id;
            }
        }
        calc(B);
    }
    ans=(ans+mod)%mod;
    ans=(1LL*(n-1)*(n-((int)st.size()))%mod*Area(st)%mod-ans+mod)%mod;
    cout<<ans<<'\n';
    return 0;
}

  

F. Money Game 2

#include<bits/stdc++.h>
using namespace std;
 
using pii=pair<int,int>;
 
const int N=5e5+1e3+7;
 
int T,n,a[N];
 
vector<pii> L[N],R[N];
 
int chk(int a,int b,int c,int d)
{
    if(a>b)
        return chk(a,n-1,c,d)&&chk(0,b,c,d);
    if(c>d)
        return chk(a,b,c,n-1)&&chk(a,b,0,d);
    return a>d||c>b;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i],L[i].clear(),R[i].clear();
        if(n==1)
        {
            cout<<a[0]<<"\n";
            continue;
        }
        for(int r=0;r<n*2;r++)
        {
            int i=r%n;
            auto tmp=L[(i+n-1)%n];
            if(tmp.size()&&tmp.begin()->second==i)
                tmp.erase(tmp.begin());
            tmp.push_back({0,i});
            L[i].clear();
            reverse(tmp.begin(),tmp.end());
            for(auto [x,y]:tmp)
            {
                if(!L[i].size()||x/2+a[i]!=L[i].back().first)
                    L[i].push_back({x/2+a[i],y});
            }
            reverse(L[i].begin(),L[i].end());
        }
        for(int r=n*2-1;r>=0;r--)
        {
            int i=r%n;
            auto tmp=R[(i+1)%n];
            if(tmp.size()&&tmp.begin()->second==i)
                tmp.erase(tmp.begin());
            tmp.push_back({0,i});
            R[i].clear();
            reverse(tmp.begin(),tmp.end());
            for(auto [x,y]:tmp)
            {
                if(!R[i].size()||x/2+a[i]!=R[i].back().first)
                    R[i].push_back({x/2+a[i],y});
            }
            reverse(R[i].begin(),R[i].end());
        }
        for(int i=0;i<n;i++)
        {
        	long long ans=0;
            ans=max(ans,1ll*R[i][0].first);
            for(int j=0,k=(int)R[i].size()-1;j+1<L[i].size();j++)
            {
                while(k>0&&chk(L[i][j].second,(i+n-1)%n,(i+1)%n,R[i][k-1].second))
                    k--;
                ans=max(ans,1ll*R[i][k].first+L[i][j].first-a[i]);
            }
        	cout<<ans<<" \n"[i+1==n];
        }
    }
}

  

G. Yelkrab

#include<bits/stdc++.h>
using namespace std;
 
const int N=1e6+1e3+7;
 
int T,n,sz[N];
 
vector<int> fac[N];
 
int son[N][26],ans[N];
 
string s[N];
 
int t;
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    for(int i=1;i<=500000;i++)
        for(int j=i;j<=500000;j+=i)
            fac[j].push_back(i);
    cin>>T;
    while(T--)
    {
        cin>>n;
        memset(son[0],-1,sizeof(son[0]));
        t=0;
        for(int i=1;i<=n;i++)
            ans[i]=0;
        int ANS=0;
        for(int i=1;i<=n;i++)
        {
            string s;
            cin>>s;
            int x=0;
            for(auto c:s)
            {
                c-='a';
                if(son[x][c]==-1)
                {
                    son[x][c]=++t;
                    sz[t]=0;
                    memset(son[t],-1,sizeof(son[t]));
                }
                x=son[x][c];
                sz[x]++;
                for(auto p:fac[sz[x]])
                {
                    ANS^=ans[p]*p;
                    ans[p]++;
                    ANS^=ans[p]*p;
                }
            }
            cout<<ANS<<" \n"[i==n];
        }
    }
}

  

H. Mah-jong

#include <bits/stdc++.h>
using namespace std;
const int D = 8;
vector<int> g(D - 2) ;
typedef vector<int> vi;
typedef long long ll;
 
vector<pair<vi,vi> > t;
void dfs(int u) {
    if(u == D - 2) {
        vector<int> v(D) , lm(D);
        for(int i = 0;i < D - 2;i++) {
            v[i] += g[i];
            v[i + 1] += g[i];
            v[i + 2] += g[i];
        }
        for(int i = 0;i < D;i++) {
            lm[i] = v[i] ;
            v[i] %= 3;
        }
        t.push_back({v , lm}) ;
        return ;
    }
    for(int i = 0;i < 3;i++) {
        g[u] = i;
        dfs(u + 1);
    }
}
int n;
int a[100005];
int pre[100005][D];
int fir[D][100005];
const int D3 = 6561;
typedef pair<int,int> pii;
vector<int> tr(D);
void solv() {
    cin >> n;
    for(int i = 1;i <= n;i++) {
        cin >> a[i] ; a[i]-- ;
    }
    for(int i = 1;i <= n;i++ ) {
        for(int j = 0;j < D;j++) {
            pre[i][j] = pre[i - 1][j];
        }
        fir[a[i]][pre[i][a[i]]] = i - 1; /// for num ai , the last one with <= j
        pre[i][a[i]]++ ;
    }
    for(int j = 0;j < D;j++) fir[j][pre[n][j]] = n;
    ll ans = 0;
    for(auto &[v,lm] : t) {
        vector<int> pre(D) , pv(D);
        for(int j = 0;j < D;j++) pre[j] = ::pre[n][j] ;
        int d = 0;
        for(int j = 0;j < D;j++) {
            pv[j] = (pre[j] - v[j] + 3) % 3;
            d += pv[j] * tr[j] ;
        }
        vector<pii> qry;
        int r = n + 1;
        for(int j = 0;j < D;j++) {
            if(pre[j] < lm[j]) r = -1;
            else r = min(r , fir[j][pre[j] - lm[j]]) ;
        }
        if(r == -1) continue ;
 
        for(int i = n;i >= 1;i--) {
            r = min(r , i - 1);
            if(r != -1) {
                qry.push_back({r , d}) ;
            }
            d -= pv[a[i]] * tr[a[i]] ;
            pv[a[i]]-- ;
            if(pv[a[i]] < 0) pv[a[i]] += 3;
            d += pv[a[i]] * tr[a[i]] ;
 
            pre[a[i]]-- ;
            if(pre[a[i]] < lm[a[i]]) {r = -1; break ;}
            else r = min(r , fir[a[i]][pre[a[i]] - lm[a[i]]]) ;
        }
        
        reverse(qry.begin() , qry.end()) ;
 
 
        vector<int> sum(D) , num(D3);
        int hs = 0;
        int nxt = 0;
        for(int i = 0;i <= n;i++) {
            if(i) {
                hs -= sum[a[i]] * tr[a[i]] ;
                sum[a[i]] = (sum[a[i]] + 1) % 3;
                hs += sum[a[i]] * tr[a[i]] ;
            }
            num[hs]++ ;
            while(nxt < qry.size() && qry[nxt].first <= i) {
                ans += num[qry[nxt].second] ;
                nxt++ ;
            }
        }
    }
    cout << ans << '\n';
    return ;
}
int main() {
    ios::sync_with_stdio(false) ; cin.tie(0) ;
    dfs(0) ;
    tr[0] = 1;
    for(int i = 1;i < D;i++) tr[i] = tr[i - 1] * 3;
    int t ; cin >> t;
    while(t--) solv() ;
}

  

I. Ma Meilleure Ennemie

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace Pollard_Rho {
	mt19937 rd(time(0));
	inline int A(int x, int p) { return x >= p ? x - p : x; }
	inline int D(int x, int p) { return x < 0 ? x + p : x; }
	inline int Mul(int x, int y, int p) {
		return D(A(x * y - (int)((long double)x * y / p) * p, p), p);
	}
	inline int Qpow(int x, int y, int p) {
		int ans = 1;
		for (; y; y >>= 1, x = Mul(x, x, p)) if (y & 1) ans = Mul(ans, x, p);
		return ans;
	}
	inline bool Mr(int x, int b) {
		int k = x - 1;
		while (k) {
			int cur = Qpow(b % x, k, x);
			if (cur != 1 && cur != x - 1) return 0;
			if ((k & 1) || cur == x - 1) return 1;
			k >>= 1;
		}
		return 1;
	}
	int p[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
	inline bool IsPrime(int n) {
		if (n <= 1 || n == 46856248255981ll) return 0;
		for(int i = 0; i < 7; i++) {
			if(p[i] % n == 0)
				continue;
			if(n == p[i])
				return 1;
			if(!Mr(n, p[i]))
				return 0;
		}
		return 1;
		// if (n == 2 || n == 61) return 1;
		// return Mr(n, 2) && Mr(n, 61);
	}
	inline int Pr(int x) {
		int s = 0, t = 0, c = rd() % (x - 1) + 1;
		int stp = 0, goal = 1;
		int val = 1;
		for (goal = 1; ; goal <<= 1, s = t, val = 1) {
			for (stp = 1; stp <= goal; ++stp) {
				t = A(Mul(t, t, x) + c, x);
				val = Mul(val, abs(t - s), x);
				if ((stp & 127) == 0) {
					int d = __gcd(val, x);
					if (d > 1) return d;
				}
			}
			int d = __gcd(val, x);
			if (d > 1) return d;
		}
	}
	inline void Divide(int n, map<int, int> &ans) {
		if (n <= 1) return;
		if (IsPrime(n)) return void(++ans[n]);
		int x = n;
		while (x == n) x = Pr(n);
		Divide(x, ans); Divide(n / x, ans);
	}
	inline map<int, int> Factor(int x) {
		map<int, int> ans;
		Divide(x, ans);
		return ans;
	}
}
 
int n, m;
 
vector<int> fac, id, wid;
 
const int P = 998244353;
 
vector<int> prod;
 
int qpow(int a, int b) {
    b %= P - 1;
    int ret = 1;
    while(b) {
        if(b & 1)
            ret = ret * a % P;
        b >>= 1;   
        a = a * a % P;
    }
    return ret;
}
 
signed main() {
    cin >> n >> m;
	if(n == 1) {
		cout << m % P << "\n";
		return 0;
	}
    auto tmp = Pollard_Rho::Factor(n);
    for(auto [x, y] : tmp)
        fac.push_back(x);
    prod.resize(1 << fac.size(), 1);
	wid.resize(prod.size());
	id.resize(fac.size());
	id[0] = 1;
	for(int i = 1; i < fac.size(); i += 1)
		id[i] = id[i - 1] * (tmp[fac[i - 1]] + 1);
    for(int S = 0; S < (1 << fac.size()); S += 1) 
        for(int i = 0; i < fac.size(); i += 1)
            if(S >> i & 1)
                prod[S] *= fac[i], wid[S] += id[i];
	int ID = 0;
	for(int i = 0; i < fac.size(); i += 1)
		ID += id[i] * tmp[fac[i]];
	vector<int> dp(ID + 1, 0), wn(ID + 1, 0), wm(ID + 1, 0);
	wn[ID] = n, wm[ID] = m;
	for(int i = ID; i >= 0; i -= 1) {
		for(int j = 0; j < fac.size(); j += 1) {
			if(wn[i] % fac[j] == 0) {
				wn[i - id[j]] = wn[i] / fac[j];
				wm[i - id[j]] = wm[i] / fac[j];
			}
		}
	}
	for(int i = 0; i <= ID; i += 1) {
		int T = 0;
		for(int j = 0; j < fac.size(); j += 1)
			if(wn[i] % fac[j] == 0)
				T ^= 1 << j;
		int ret = 0;
		for(int S = T;;S = (S - 1) & T) {
			int mu = __builtin_parity(S) ? -1 : 1;
			int e = prod[S];
			ret += mu * (wm[i] / e);
			if(S) {
				ret -= mu * qpow(dp[i - wid[S]], e);
			}
			if(!S)
				break;
		}
		dp[i] = (ret % P + P) % P;
	}
	cout << dp[ID] << "\n";
	return 0;
}

  

J. Reconstruction

#include<bits/stdc++.h>
using namespace std;
const int N=500050;
int n,ok[N];
vector<int> G[N],H[N];
struct Union_Set{
    int f[N];
    void init(int n){
        for(int i=1;i<=n;++i){
            f[i]=i;
        }
    }
    inline int getf(int x){
        return f[x]==x?x:f[x]=getf(f[x]);
    }
}S;
int vis[N];
int dfs(int u,int fa){
    for(auto v:H[u]){
        if(v==fa)continue;
        int x=dfs(v,u);
        if(x)return x;
    }
    for(auto v:G[u]){
        vis[S.getf(v)]=u;
    }
    for(auto v:H[u]){
        if(v==fa)continue;
        if(vis[v]!=u)return v;
        S.f[S.getf(v)]=u;
    }
    return 0;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for(int i=1;i<n;++i){
        int u,v;
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i=1;i<n;++i){
        int u,v;
        cin>>u>>v;
        H[u].push_back(v);
        H[v].push_back(u);
    }
    S.init(n);
    int rt=dfs(1,0),OK=0;
    if(!rt)rt=1,OK=1;
    memset(vis,0,sizeof(vis));
    S.init(n);
    if(OK||!dfs(rt,0)){
        memset(vis,0,sizeof(vis));
        queue<int> q;
        q.push(rt);
        ok[rt]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(auto v:G[u]){
                vis[v]=u;
            }
            for(auto v:H[u]){
                if(vis[v]&&!ok[v]){
                    ok[v]=1;
                    q.push(v);
                }
            }
        }
    }
    for(int i=1;i<=n;++i){
        cout<<ok[i];
    }
    cout<<'\n';
    return 0;
}

  

K. LR String

#include <bits/stdc++.h>
using namespace std;
string s ;
int q;
const int N = 5e5 + 5;
int nxt[N][2];
const int inf = 1e9;
void solv() {
    cin >> s >> q;
    int c[2] = {inf , inf} ;
    for(int i= s.size() - 1;i >= 0;i--) {
        nxt[i][0] = c[0];
        nxt[i][1] = c[1];
        if(s[i] == 'L') c[0] = i;
        else c[1] = i;
    }
    while(q--) {
        string t ; cin >> t;
        if(s[0] == 'L' && t[0] != 'L') {
            cout << "NO\n"; continue ;
        }
        if(s.back() == 'R' && t.back() != 'R') {
            cout << "NO\n" ; continue ;
        }
        bool ff = 1;
        int u = (t[0] == 'L' ? c[0] : c[1]);
        for(int i = 1;i < t.size();i++) {
            if(u >= s.size()) {
                ff = 0 ; break ;
            }
            if(t[i] == 'L') u = nxt[u][0];
            else u = nxt[u][1] ;
            if(u >= s.size()) {
                ff = 0 ; break ;
            }
        }
        cout << (ff ? "YES\n" : "NO\n") ;
    }
    return ;
}
int main() {
    ios::sync_with_stdio(false) ; cin.tie(0) ;
    int t ; cin >> t;
    while(t--) solv() ;
}

  

L. Flipping Paths

#include<bits/stdc++.h>
using namespace std;
int main()
{
	ios_base::sync_with_stdio(false);
	int T;
	cin>>T;
	while(T--)
	{
		int n,m;
		cin>>n>>m;
		vector<string> s(n+5);
		for(int i=1;i<=n;i++)
		{
			string t;
			cin>>t;
			s[i]=' '+t;
		}
		if(n==1 and m==1)
		{
			cout<<"YES\n0\n";
			continue;
		}
		if(n==3 and m==3 and s[1]==" WBB" and s[2]==" BWB" and s[3]==" BBW")
		{
			cout<<"YES\n2\nRRDD\nDDRR\n";
			continue;
		}
		if(n==2 and m==2 and s[1]==" BB" and s[2]==" BB")
		{
			cout<<"YES\n0\n";
			continue;
		}
		if(n==1 and m==5 and s[1]==" WWWWW")
		{
			cout<<"YES\n0\n";
			continue;
		}
		vector<string> ans;
		int ok=0;
		auto tmp=s;
		auto flip=[&](char &ch){ch='B'+'W'-ch;};
		for(auto ch:"BW")
		{
			s=tmp;
			ans.clear();
			for(int diag=m-2;diag>=1-n;diag--)//y-x
			{
				string op;
				int x=1,y=1;
				while(y-x<diag)flip(s[x][y]),y++,op+='R';
				while(y-x>diag)flip(s[x][y]),x++,op+='D';
				while(x<n and y<m)
				{
					if(s[x][y+1]!=ch)
					{
						flip(s[x][y]),y++,op+='R';
						flip(s[x][y]),x++,op+='D';
					}
					else
					{
						flip(s[x][y]),x++,op+='D';
						flip(s[x][y]),y++,op+='R';
					}
				}
				while(y<m)flip(s[x][y]),y++,op+='R';
				while(x<n)flip(s[x][y]),x++,op+='D';
				flip(s[x][y]);
				ans.push_back(op);
				
				if(diag<=2-n)
				{
					int done=1;
					for(int i=1;i<=n;i++)
					{
						for(int j=1;j<=m;j++)
						{
							if(s[i][j]!=ch)
								done=0;
						}
					}
					if(done)
					{
						ok=1;
						break;
					}
				}
			}
			if(ok)break;
		}
		if(ok)
		{
			cout<<"YES\n"<<ans.size()<<endl;
			for(auto row:ans)
				cout<<row<<endl;
		}
		else
		{
			cout<<"NO\n";
		}
	}
	
	return 0;
}

  

M. Godzilla

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int,int>P;
typedef unsigned short U;
const int N=77,M=N*2,K=8,CE=N*N;
int n,m,ce,i,j,optd,optv,opt[4],f[M];
int maxd[4],two[4],twoedges[4],edge[3][3][4][2],extra[3][4];
struct E{int x,y,d,v;bool ban;}e[CE];
struct Basis{
  int f,s,d,v;
  bool oncircle,del;
}basis[M];
vector<int>adj[M];
int dfn,st[M],en[M],ccom,at[M],root[M],cir[M],delid[3];
struct Ranges{
  vector<P>seg;
  int r,nxt;
  void init(int _l,int _r){
    seg.clear();
    r=_r;
    nxt=_l;
  }
  void append(int l,int r){
    if(nxt<l)seg.emplace_back(P(nxt,l-1));
    nxt=r+1;
  }
  void finish(){
    if(nxt>r)return;
    seg.emplace_back(P(nxt,r));
  }
  bool find(int x)const{
    for(const auto&it:seg)if(it.first<=x&&x<=it.second)return 1;
    return 0;
  }
  void addtotree(vector<P>&v){
    for(const auto&it:seg)v.emplace_back(it);
  }
};
U top[4],top2[4][2];int Log[M];
inline void upu(U&a,U b){a<b?(a=b):0;}
struct RMQ{
  U f[K][M][4][2];
  void init(){
    for(int i=1;i<=n;i++)for(int j=0;j<4;j++)for(int k=0;k<2;k++)f[0][i][j][k]=0;
  }
  void build(){
    for(int i=1;(1<<i)<=n;i++)for(int j=1;j+(1<<i)-1<=n;j++)for(int k=0;k<4;k++){
      const auto&A=f[i-1][j][k];
      const auto&B=f[i-1][j+(1<<(i-1))][k];
      auto&C=f[i][j][k];
      if(A[0]>B[0]){
        C[0]=A[0];
        C[1]=max(A[1],B[0]);
      }else if(A[0]<B[0]){
        C[0]=B[0];
        C[1]=max(A[0],B[1]);
      }else{
        C[0]=A[0];
        C[1]=max(A[1],B[1]);
      }
    }
  }
  void fetchtop(const P&seg)const{
    int k=Log[seg.second-seg.first+1];
    const auto&L=f[k][seg.first];
    const auto&R=f[k][seg.second-(1<<k)+1];
    for(int i=0;i<4;i++){
      upu(top[i],L[i][0]);
      upu(top[i],R[i][0]);
    }
  }
  void fetchtop2(const P&seg)const{
    int k=Log[seg.second-seg.first+1];
    const auto&L=f[k][seg.first];
    const auto&R=f[k][seg.second-(1<<k)+1];
    for(int i=0;i<4;i++){
      const auto&A=L[i];
      const auto&B=R[i];
      auto&C=top2[i];
      if(C[0]>=A[0]&&C[0]>=B[0]){
        upu(C[1],A[A[0]==C[0]]);
        upu(C[1],B[B[0]==C[0]]);
      }else if(C[0]>=A[0]){
        C[1]=max(C[0],B[1]);
        C[0]=B[0];
      }else if(C[0]>=B[0]){
        C[1]=max(C[0],A[1]);
        C[0]=A[0];
      }else if(A[0]>B[0]){
        C[1]=max(C[0],A[1]);
        upu(C[1],B[0]);
        C[0]=A[0];
      }else if(A[0]<B[0]){
        C[1]=max(C[0],B[1]);
        upu(C[1],A[0]);
        C[0]=B[0];
      }else{
        C[1]=max(C[0],A[1]);
        upu(C[1],B[1]);
        C[0]=A[0];
      }
    }
  }
};
vector<RMQ>rmq[M];
inline bool cmpe(const E&a,const E&b){return a.d<b.d;}
int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
inline void up(int&a,int b){a<b?(a=b):0;}
inline void solve2edges(int A,int B){
  int i,j;
  for(i=0;i<4;i++)twoedges[i]=0;
  for(i=0;i<4;i++)if(edge[A][B][i][0])
    for(j=0;j<=i;j++)if(edge[A][B][j][i==j])
      up(twoedges[(i+j)&3],edge[A][B][i][0]+edge[A][B][j][i==j]);
}
inline void solve2components(int A,int B){
  int i,j;
  solve2edges(A,B);
  static int one[4];
  for(i=0;i<4;i++){
    one[i]=max(extra[A][i],extra[B][i]);
    two[i]=twoedges[i];
  }
  for(i=0;i<4;i++)if(extra[A][i])
    for(j=0;j<4;j++)if(extra[B][j])
      up(two[(i+j)&3],extra[A][i]+extra[B][j]);
  for(i=0;i<4;i++)if(edge[A][B][i][0])
    for(j=0;j<4;j++)if(one[j])
      up(two[(i+j)&3],edge[A][B][i][0]+one[j]);
}
inline bool cmpv(int x,int y){return st[x]<st[y];}
inline void solve(int cntdel){
  int i,j,k,x,y;
  static int T,lastcom[M];
  T++;
  static vector<int>poolcom;
  poolcom.clear();
  for(i=0;i<cntdel;i++){
    int o=delid[i];
    x=basis[o].s;
    y=at[x];
    if(lastcom[y]!=T){
      lastcom[y]=T;
      poolcom.emplace_back(y);
    }
  }
  int ctree=0;
  static vector<P>tree[3];
  for(i=0;i<cntdel;i++)tree[i].clear();
  for(const auto&x:poolcom){
    int S=root[x];
    int L=st[S],R=en[S];
    int pos=cir[x]?st[basis[cir[x]].s]:0;
    static int pool[4];
    pool[0]=S;
    int cp=1;
    for(j=0;j<cntdel;j++)if(!basis[delid[j]].oncircle){
      y=basis[delid[j]].s;
      if(at[y]==x)pool[cp++]=y;
    }
    sort(pool,pool+cp,cmpv);
    static int q[4];
    int top=0;
    q[0]=0;
    static Ranges ranges[4];
    ranges[0].init(L,R);
    for(i=1;i<cp;i++){
      y=pool[i];
      while(en[pool[q[top]]]<st[y])top--;
      ranges[q[top]].append(st[y],en[y]);
      q[++top]=i;
      ranges[i].init(st[y],en[y]);
    }
    for(i=0;i<cp;i++)ranges[i].finish();
    if(pos&&!basis[cir[x]].del){
      for(i=0;i<cp;i++)if(ranges[i].find(pos))break;
      if(!i)for(j=1;j<cp;j++)ranges[j].addtotree(tree[ctree++]);
      else{
        ranges[0].addtotree(tree[ctree]);
        ranges[i].addtotree(tree[ctree]);
        sort(tree[ctree].begin(),tree[ctree].end());
        ctree++;
        for(j=1;j<cp;j++)if(j!=i)ranges[j].addtotree(tree[ctree++]);
      }
    }else for(j=0;j<cp;j++)ranges[j].addtotree(tree[ctree++]);
  }
  static vector<P>all,outer;
  all.clear();
  outer.clear();
  for(i=0;i<ctree;i++)for(const auto&it:tree[i])all.emplace_back(it);
  sort(all.begin(),all.end());
  int r=0;
  for(const auto&it:all){
    if(r+1<it.first)outer.emplace_back(P(r+1,it.first-1));
    up(r,it.second);
  }
  if(r<n)outer.emplace_back(P(r+1,n));
  for(i=0;i<ctree;i++){
    for(j=0;j<4;j++)top[j]=0;
    for(const auto&A:tree[i]){
      const auto&ds=rmq[A.second][A.first];
      for(const auto&B:tree[i]){
        ds.fetchtop(B);
        if(B.first==A.first)break;
      }
      for(const auto&B:outer)ds.fetchtop(B);
    }
    for(j=0;j<4;j++)extra[i][j]=e[top[j]].d;
    for(j=i+1;j<ctree;j++){
      for(k=0;k<4;k++)for(x=0;x<2;x++)top2[k][x]=0;
      for(const auto&A:tree[i]){
        const auto&ds=rmq[A.second][A.first];
        for(const auto&B:tree[j])ds.fetchtop2(B);
      }
      for(k=0;k<4;k++)for(x=0;x<2;x++){
        int id=top2[k][x];
        edge[i][j][k][x]=edge[j][i][k][x]=e[id].d;
      }
    }
  }
  if(ctree==1){
    for(i=0;i<4;i++)maxd[i]=extra[0][i];
    return;
  }
  if(ctree==2){
    solve2components(0,1);
    for(i=0;i<4;i++)maxd[i]=two[i];
    return;
  }
  for(i=0;i<4;i++)maxd[i]=0;
  for(i=0;i<4;i++)if(edge[0][1][i][0])
    for(j=0;j<4;j++)if(edge[0][2][j][0])
      for(k=0;k<4;k++)if(edge[1][2][k][0])
        up(maxd[(i+j+k)&3],edge[0][1][i][0]+edge[0][2][j][0]+edge[1][2][k][0]);
  static int common[4];
  for(i=0;i<4;i++){
    common[i]=0;
    for(j=0;j<3;j++)up(common[i],extra[j][i]);
  }
  for(int S=0;S<3;S++){
    int A=(S+1)%3,B=(S+2)%3;
    solve2components(A,B);
    for(i=0;i<4;i++)if(two[i])
      for(j=0;j<4;j++)if(extra[S][j])
        up(maxd[(i+j)&3],two[i]+extra[S][j]);
    for(i=0;i<4;i++)if(edge[S][A][i][0])
      for(j=0;j<4;j++)if(edge[S][B][j][0])
        for(k=0;k<4;k++)if(common[k])
          up(maxd[(i+j+k)&3],edge[S][A][i][0]+edge[S][B][j][0]+common[k]);
    for(int _=0;_<2;_++){
      solve2edges(S,A);
      for(i=0;i<4;i++)if(twoedges[i])
        for(j=0;j<4;j++)if(edge[S][B][j][0])
          up(maxd[(i+j)&3],twoedges[i]+edge[S][B][j][0]);
      swap(A,B);
    }
  }
}
void dfs(int x,int y){
  at[x]=ccom;
  st[x]=++dfn;
  for(const auto&id:adj[x]){
    int u=basis[id].f^basis[id].s^x;
    if(u==y)continue;
    if(u!=basis[id].s)swap(basis[id].f,basis[id].s);
    dfs(u,x);
  }
  en[x]=dfn;
}
inline void newcom(int S){
  root[++ccom]=S;
  dfs(S,0);
}
void search(int o,int x){
  if(o){
    solve(o);
    for(int i=0;i<4;i++)if(maxd[i])up(opt[(optv+i)&3],optd+maxd[i]);
  }
  if(o==3)return;
  for(;x<=n;x++){
    optd-=basis[x].d;
    (optv+=4-basis[x].v)&=3;
    basis[x].del=1;
    delid[o]=x;
    search(o+1,x+1);
    optd+=basis[x].d;
    (optv+=basis[x].v)&=3;
    basis[x].del=0;
  }
}
int main(){
  scanf("%d%d",&n,&m);
  for(i=1;i<=n;i++)for(j=1;j<=m;j++){
    e[++ce].x=i;
    e[ce].y=j+n;
    scanf("%d",&e[ce].d);
  }
  ce=0;
  for(i=1;i<=n;i++)for(j=1;j<=m;j++){
    scanf("%d",&e[++ce].v);
    e[ce].v&=3;
  }
  n+=m;
  sort(e+1,e+ce+1,cmpe);
  static bool g[M];
  for(i=1;i<=n;i++)f[i]=i;
  m=0;
  for(i=ce;i;i--){
    int x=F(e[i].x),y=F(e[i].y);
    if(g[x]&&g[y])continue;
    ++m;
    basis[m].f=e[i].x;
    basis[m].s=e[i].y;
    basis[m].d=e[i].d;
    basis[m].v=e[i].v;
    e[i].ban=1;
    optd+=e[i].d;
    (optv+=e[i].v)&=3;
    if(x==y){
      g[x]=1;
      basis[m].oncircle=1;
    }else{
      f[x]=y;
      g[y]|=g[x];
      adj[e[i].x].emplace_back(m);
      adj[e[i].y].emplace_back(m);
    }
  }
  opt[optv]=optd;
  for(i=1;i<=n;i++)if(basis[i].oncircle){
    newcom(basis[i].f);
    cir[ccom]=i;
  }
  for(i=1;i<=n;i++)if(!st[i])newcom(i);
  for(i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
  for(i=1;i<=n;i++){
    rmq[i].resize(i+1);
    for(j=1;j<=i;j++)rmq[i][j].init();
  }
  for(i=ce;i;i--)if(!e[i].ban){
    int x=st[e[i].x],y=st[e[i].y],val=e[i].v;
    for(int _=0;_<2;_++){
      for(int r=x;r<=n;r++)for(int l=x;l;l--){
        auto&f=rmq[r][l].f[0][y][val];
        if(!f[0])f[0]=i;
        else if(f[0]!=i&&!f[1])f[1]=i;
        else break;
      }
      swap(x,y);
    }
  }
  for(i=1;i<=n;i++)for(j=1;j<=i;j++)rmq[i][j].build();
  search(0,1);
  for(i=0;i<4;i++){
    if(!opt[i])opt[i]=-1;
    printf("%d\n",opt[i]);
  }
}

  

posted @ 2025-01-12 03:08  Claris  阅读(555)  评论(0)    收藏  举报