组队训练记录(2):2020CCPC长春

2022.9.6
在这里插入图片描述
四题银首(然而学长首战这场Au),感觉实力还是不行。

A. Krypton

dp 队友写的 没看

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

const int N = 2e5 + 10;
int a[9]={0,1,6,28,88,198,328,648};
int w[9]= {0,18,78,308,938,2108,3478,6868};
int ww[9]={0,10,60,280,880,1980,3280,6480};
int f[N];
inline void solve(){
    int n; cin>>n;
    for(int i=1;i<=7;i++)
    {
        for(int j=n;j>=a[i];j--) 
        {
            f[j]=max(f[j],f[j-a[i]]+w[i]);
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,f[i]+(n-i)*10);
    }
    cout<<ans<<"\n";
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int t = 1; //cin >> t;
    while(t--) solve();
    return 0;
}

D. Meaningless Sequence

类似数位dp的计数。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

const int N = 2e5 + 10,mod=1000000007;

int qpow(int x,int y=mod-2,int mo=mod,int res=1){
    for(;y;y>>=1,(x*=x)%=mo) if(y&1)(res*=x)%=mo;
    return res;
}
int jie[300005],invjie[300005],base[300005];
string s;
int ans,c,n,cnt;
int C(int n,int m){
    return jie[n]*invjie[m]%mod*invjie[n-m]%mod;
}
inline void solve(){
    jie[0]=base[0]=1;
    cin>>s>>c;
    for(int i=1;i<=N;i++){
        jie[i]=jie[i-1]*(i)%mod;
        base[i]=base[i-1]*c%mod;
    }
    invjie[N]=qpow(jie[N]);
    for(int i=N-1;~i;i--){
        invjie[i]=invjie[i+1]*(i+1)%mod;
    }
    n=s.size();
    s=" "+s;
    for(int i=1;i<=n;i++){
        if(s[i]=='1'){
            for(int j=0;j+i<=n;j++){
                (ans+=C(n-i,j)*base[j+cnt]%mod)%=mod;
            }
            cnt++;
        }
    }
    (ans+=base[cnt])%=mod;
    cout<<ans<<endl;
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int t = 1; //cin >> t;
    while(t--) solve();
    return 0;
}

F. Strange Memory

树上启发式合并板子题,第一次vp的时候写,竟然40min就调完了。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

const int N = 2e5 + 10,mod=1000000007;

int qpow(int x,int y=mod-2,int mo=mod,int res=1){
    for(;y;y>>=1,(x*=x)%=mo) if(y&1)(res*=x)%=mo;
    return res;
}
int sz[200005],dfn[200005],w[200005],f[200005],idx;
int lst[200005],a[200005];
int st[1000005][18];
int ans,cnt[1000005];
vector<int>p[200005];
int n;
void dfs1(int u,int fa){
    f[u]=fa;
    if(fa!=0)p[u].erase(find(p[u].begin(),p[u].end(),fa));
    sz[u]++;
    for(auto v:p[u]){
        dfs1(v,u);
        sz[u]+=sz[v];
    }
    sort(p[u].begin(),p[u].end(),[](int x,int y){return sz[x]>sz[y];});
}
void dfs2(int u){
    dfn[u]=++idx;
    a[idx]=u;
    for(auto v:p[u]){
        dfs2(v);
    }
    lst[u]=idx;
}
void del(int u){
    for(int i=dfn[u];i<=lst[u];i++){
        int id=a[i],wid=w[id];
        cnt[wid]--;
        for(int j=0;j<17;j++){
            st[wid][j]-=((id>>j)&1);
        }
    }
}
void add(int u){
    for(int i=dfn[u];i<=lst[u];i++){
        int id=a[i],wid=w[id];
        cnt[wid]++;
        for(int j=0;j<17;j++){
            st[wid][j]+=((id>>j)&1);
        }
    }
}
void addans(int x,int id){
    if(x>1000000)return;
    for(int i=0;i<17;i++){
        if(id>>i&1){
            ans+=(1<<i)*(cnt[x]-st[x][i]);
        }
        else{
            ans+=(1<<i)*st[x][i];
        }
    }
}
void dfs(int u){
    for(auto v:p[u]){
        if(v==p[u][0])continue;
        dfs(v);
        del(v);
    }
    if(p[u].size())dfs(p[u][0]);
    for(auto v:p[u]){
        if(v==p[u][0])continue;
        for(int i=dfn[v];i<=lst[v];i++){
            addans(w[a[i]]^w[u],a[i]);
        }
        add(v);
    }
    cnt[w[u]]++;
    for(int j=0;j<17;j++){
        st[w[u]][j]+=((u>>j)&1);
    }
}
inline void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i];
    }
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        p[u].push_back(v);
        p[v].push_back(u);
    }
    dfs1(1,0);
    dfs2(1);
    dfs(1);
    cout<<ans<<endl;
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int t = 1; //cin >> t;
    while(t--) solve();
    return 0;
}

K. Ragdoll

启发式合并,队友写了 调了3h,机时太久最后网络流H也没调出来。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

const int N = 4e5 + 10;

namespace unionfind{
    int par[N];
    inline void init(int n){ for(int i = 1; i <= n; i++) par[i] = i; }
    int find(int i){ return (par[i] == i ? i : (par[i] = find(par[i]))); }
    void merge(int x, int y){ par[x] = y; }
    void initfa(int x) { par[x] = x; }
}


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

signed w[N], siz[N];
int ans = 0;

vector<int> pf[N];
unordered_map<int, int> cnt[N];

void init(){
    vector<int> fac;
    for(int i = 2; i <= 3e5; i++){
        fac.clear();
        for(int j = 1; j * j <= i; j++){
            if(i % j == 0) {
                fac.emplace_back(j);
                if(j * j != i) fac.emplace_back(i / j);
            }
        }
        for(auto x : fac){
            if(__gcd(i , (i ^ x)) == x && (i ^ x)){
                pf[i].emplace_back(i ^ x);
            }
        }
    }
}

inline void make_node(int id, int val){
    siz[id] = 1, w[id] = val, cnt[id][val]++, unionfind::initfa(id);
}


void merge(int u, int v){
    int ufa = unionfind::find(u), vfa = unionfind::find(v);
    if(ufa == vfa) return;
    if(siz[ufa] < siz[vfa]) swap(ufa, vfa);
    for(auto [nval, ncount] : cnt[vfa]){
        for(auto nfac : pf[nval]){
            auto it=cnt[ufa].find(nfac);
            if(it != cnt[ufa].end()) ans += ncount * (*it).second;
        }
    }
    for(auto [nval, ncount] : cnt[vfa]){
        if(!cnt[ufa].count(nval) || !cnt[ufa][nval]) siz[ufa]++;
        cnt[ufa][nval] += ncount;
    }
    // cnt[ufa].clear();
    unionfind::merge(vfa, ufa);
}

void modify(int u, int val){
    int ufa = unionfind::find(u);
    for(auto fac : pf[w[u]]){
        auto it = cnt[ufa].find(fac);
        if(it != cnt[ufa].end()) ans -= it -> second;
    }
    cnt[ufa][w[u]]--;
    if(!cnt[ufa].count(w[u]) || !cnt[ufa][w[u]]) siz[ufa]--, cnt[ufa].erase(w[u]);
    w[u] = val, cnt[ufa][w[u]]++;
    if(cnt[ufa][w[u]] == 1) siz[ufa]++;
    for(auto fac : pf[w[u]]){
        auto it = cnt[ufa].find(fac);
        if(it != cnt[ufa].end()) ans += it -> second;
    }
}


inline void solve(){
    int n = read(), m = read();
    // unionfind::init(n);
    for(int i = 1; i <= n; i++) make_node(i, read());
    while(m--){
        int op = read(), l = read(), r = read();
        if(op == 1) make_node(l, r);
        else if (op == 2) merge(l, r);
        else modify(l, r);
        // assert(ans < INT_MAX);
        printf("%lld\n", ans);
    }
}

signed main(){
    init(), solve();
    return 0;
}

/*






*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值