2020ccpc长春站

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

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);
    }


}
全部评论

相关推荐

不愿透露姓名的神秘牛友
05-29 15:00
教授A:“你为什么要讲这么久,是要压缩我们对你的评议时间吗?你们别以为这样就能够让我们对你们少点意见。”&nbsp;“从你的发言和论文格式就能知道你的性格啊。”…….&nbsp;感觉被狠狠霸凌了。
码农索隆:“教授您好,首先我想回应您提出的两点疑问。” “关于我讲解时间较长的问题:这绝非为了压缩各位老师的评议时间。这份毕业设计是我过去几个月倾注了全部心血的作品,从构思、实验、调试到撰写,每一个环节都反复打磨。我深知时间宝贵,所以选择详细讲解,是希望能更完整、清晰地展示它的核心创新点、实现过程和验证结果,确保老师们能充分理解它的价值和我的努力。我完全理解并重视评审环节的意义,也做好了充分准备来听取各位老师的专业意见和批评。几个月的研究都坚持下来了,我怎么可能害怕老师们的点评呢?今天站在这里,正是抱着虚心学习、诚恳求教的态度而来。” “如果我的展示确实超时,影响了后续流程,烦请老师们随时示意,我会立刻调整。我非常期待并预留了充足的时间,希望能听到老师们宝贵的建议和深入的讨论。” “其次,关于您提到‘从发言和论文格式就能知道我的性格’。教授,我对此感到非常困惑和不安。学术研究和答辩的核心,难道不应该是作品本身的质量、逻辑的严谨性、数据的可靠性和结论的合理性吗?论文格式有明确的规范要求,我尽最大努力遵循了这些规范。如果格式上存在疏忽或不足,这属于技术性、规范性的问题,恳请老师们具体指出,我一定认真修改。但将格式问题或个人表达风格(如讲解时长)直接上升为对个人性格的评判,甚至以此作为质疑我学术态度和动机的依据,这让我感到非常不公平,也偏离了学术评议应有的客观和严谨原则。” “我尊重每一位评审老师的专业权威,也衷心希望能得到老师们对我的工作内容本身的专业指导和批评指正。任何基于研究本身的意见,无论多么尖锐,我都会认真聆听、反思并改进。但我恳请老师们,能将评议的焦点放在我的研究本身,而不是对我个人进行主观的推断或评价。谢谢各位老师。”
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务