菜鸡赛后补的题(本校有大佬拿了金牌%%%)

A - Krypton

暴力枚举所有组合(2^7)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
typedef long long ll;
inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
int t, n, a[maxn], b[maxn];
char s[maxn];
int main() {
    n = read();
    int ans = 0;
    a[1] = 1; a[2] = 6; a[3] = 28; a[4] = 88; a[5] = 198; a[6] = 328; a[7] = 648;
    b[1] = 8; b[2] = 18; b[3] = 28; b[4] = 58; b[5] = 128; b[6] = 198; b[7] = 388;
    for (int i = 1; i < (1<<7); i++) {
        int tmp = 0, res = 0;
        for (int j = 0; j < 7; j++) {
            if((i>>j)&1) tmp += a[j + 1], res += b[j + 1];
        }
        if(tmp > n) continue;
        res += n * 10;
        ans = max(ans, res);
    }
    printf("%d\n", ans);
    return 0;
}

D - Meaningless Sequence

打表找规律,发现ai的值就是c的次方数(ai二进制1的个数)的值。然后比较裸的数位dp.

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int mod=1e9+7;

ll dp[3005][2];
char d[3005];
int n,c;

ll dfs( ll now,bool limit )
{
    if( now==-1 ) return 1;
    if( dp[now][limit] ) return dp[now][limit];

    int up=limit ? d[now]-'0': 1;
    ll res=0;
    for( int i=0;i<=up;i++ )
    {
        res+=dfs( now-1,limit && i==up )*( i==1 ? c : 1 )%mod ;
        res%=mod;
    }
    return dp[now][limit]=res;
}

int main()
{

    scanf("%s%d",&d,&c);
    int n=strlen(d);
    reverse(d,d+n);
    printf("%lld\n",dfs(n-1,1));
} 

F - Strange Memory

看题目的式子就往dsu想,枚举轻链然后找点对。由于求得贡献是下标的异或值,所以我们将点权作为数组下标,然后开20位空间,记录对应权值的下标二进制下各位的1的个数。(有个坑点,二进制拆解下标记得用for循环20次,不要用while(y) )

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+10;
typedef unsigned long long ll;
int head[maxn],to[maxn<<1],nex[maxn<<1],tot,a[maxn];
int n,k;

void add( int x,int y )
{
    to[tot]=y;nex[tot]=head[x];
    head[x]=tot++;
}

int fa[maxn],siz[maxn],son[maxn],nowson,dep[maxn];
ll sum[maxn],ans[maxn],num[maxn];

void dfs( int x,int f )
{
    fa[x]=f;
    dep[x]=dep[f]+1;
    siz[x]=1;
    for( int i=head[x];~i;i=nex[i] )
    {
        int v=to[i];
        if( v==f ) continue;
        dfs(v,x);
        siz[x]+=siz[v];
        if( siz[v]>siz[son[x]] ) son[x]=v;
    }
}

ll sp[maxn*20][20][2];

void sol( int x,int y ,int p )
{
    int cnt=0;
    for( int i=0;i<20;i++ )
    {
        if( y>>i & 1 ) sp[x][i][1]+=p;
        else sp[x][i][0]+=p;
    }

}

void cal( int x,int p )
{
    sol(a[x],x,p);
    for( int i=head[x];~i;i=nex[i] )
    {
        int v=to[i];
        if( v==fa[x] || v==nowson ) continue;
        cal(v,p);
    }
}

void query( int x,int lca )
{
    int d=a[lca]^a[x];  // //计算贡献 改这里 
    for( int i=0;i<20;i++ )
    {
        if( x>>i & 1 ) ans[lca]+=(1ll<<i)*sp[d][i][0];
        else ans[lca]+=(1ll<<i)*sp[d][i][1];
    }

    for( int i=head[x];~i;i=nex[i] )
    {
        int v=to[i];
        if( v==fa[x] ) continue;
        query(v,lca);
    }
}


void dsu( int x,int T )
{
    for( int i=head[x];~i;i=nex[i] )
    {
        int v=to[i];
        if( v!=fa[x] && v!=son[x] ) dsu(v,0);
    }
    if( son[x] ) dsu(son[x],1),nowson=son[x];

    for( int i=head[x];~i;i=nex[i] )
    {
        int v=to[i];
        if( v==fa[x] || v==nowson ) continue;
        query(v,x);  //  //改这里  
        cal(v,1);    // //改这里 
    }
    sol(a[x],x,1);
    nowson=0;
    if( !T ) cal(x,-1);
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for( int i=1;i<=n;i++ ) scanf("%d",&a[i]);
    for( int i=1;i<n;i++ )
    {
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(1,0);
    dsu(1,1);
    ll res=0;
    for( int i=1;i<=n;i++ ) res+=ans[i];
    printf("%lld\n",res);
} 

K - Ragdoll

看题没思路的话,对着式子打表。你会发现满足gcd(i,j)==(i^j)的点对,一定满足i-j=gcd(i,j)。然后就是枚举因子打表了。
然后三种操作就是并查集的按秩合并,用unordered_map维护一下集合每种权值的个数(注意map会T).

#include<bits/stdc++.h>

using namespace std;

const int maxn=3e5+10;
typedef long long ll;
vector<ll> dd[maxn];
int a[maxn],fa[maxn];
int siz[maxn];
ll ans=0;

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

unordered_map<ll,ll> mp[maxn];

int get_fa( int x ) { return x==fa[x] ? x:fa[x]=get_fa(fa[x]); }

void solve( int fx,int fy )
{
    for( pair<ll,ll> g:mp[fy] )
    {
        for( int l=0;l<dd[g.first].size();l++ )
        {
            int tmp=dd[g.first][l];
            if( mp[fx].count(tmp) )
            {
                ans+=mp[fx][tmp]*g.second;
            }
        }
    }
    for( pair<ll,ll> g:mp[fy] ) 
    {
        mp[fx][g.first]+=g.second;
    }
    mp[fy].clear();
    fa[fy]=fx;
    siz[fx]+=siz[fy]; 
}


int main()
{
    for( int i=1;i<=2e5;i++ )
    {
        for( int j=1;j*j<=i && j<i;j++ )
        {
            if( i%j==0 )
            {
                int tmp=i-j;
                if( (tmp^i)==j )
                {
                    dd[i].push_back(tmp);
                    dd[tmp].push_back(i);
                }
                if( j*j!=i )
                {
                    int cc=i/j;
                    int tmp=i-cc;
                    if( (tmp^i)==cc )
                    {
                        dd[i].push_back(tmp);
                        dd[tmp].push_back(i);
                    }
                }
            }
        }
        sort(dd[i].begin(),dd[i].end());
        dd[i].erase(unique(dd[i].begin(),dd[i].end()),dd[i].end());
    }

    int n,m;
    n=read(),m=read();


    for( int i=1;i<=n;i++ )    a[i]=read(),fa[i]=i,siz[i]=1,mp[i][a[i]]++;


    while( m-- )
    {
        int t,x,y;
        t=read(),x=read(),y=read();
        if( t==1 )
        {
            a[x]=y;
            fa[x]=x;
            mp[x][y]++;
            siz[x]=1;
        }
        else if( t==2 )
        {
            int fx=get_fa(x),fy=get_fa(y);
            if( fx!=fy )
            {
                if( siz[fx]>siz[fy] )    solve(fx,fy);
                else solve(fy,fx);
            }
        }
        else if( t==3 )
        {
            if( y!=a[x] ) 
            {
                int fx=get_fa(x);
                for( int i=0;i<dd[a[x]].size();i++ )
                {
                    int tmp=dd[a[x]][i];
                    if( mp[fx].count(tmp) )    ans-=mp[fx][tmp];
                }
                mp[fx][a[x]]--;
                a[x]=y;
                mp[fx][y]++;
                for( int i=0;i<dd[y].size();i++ )
                {
                    int tmp=dd[y][i];
                    if( mp[fx].count(tmp) ) ans+=mp[fx][tmp];
                }
            }
        } 
        printf("%lld\n",ans);
    }


}