2017 Multi-University Training Contest 1

本文介绍了多项竞赛编程中的实用算法,包括快速计算、字符串处理、树形动态规划等,并提供了具体问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

比赛链接:2017 Multi-University Training Contest 1

A:水

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int m,T=1;
    while(~scanf("%d",&m))
    {
        printf("Case #%d: %d\n",T++,(int)(m*log10(2)));
    }
    return 0;
}

B:

将所有字符串化成系数*字母的形式,其中系数也用26进制数表示,系数大的赋权大,然后考虑不能有前导零的情况就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=1e5+7;
int c[26][N],p[26],v[26];
char s[N];
bool zero[26];
bool cmp(int a, int b)
{
    for(int i=N-1;i>=0;--i)
        if(c[a][i]>c[b][i]) return true;
        else if(c[a][i]<c[b][i]) return false;
    return false;
}
int main()
{
    int n,T=1;
    while(~scanf("%d",&n))
    {
        memset(c,0,sizeof(c));
        memset(v,-1,sizeof(v));
        memset(zero,false,sizeof(zero));
        for(int i=0;i<n;++i)
        {
            scanf("%s",s);
            int m=strlen(s);
            if(m>1) zero[s[0]-'a']=true;
            for(int j=0;j<m;++j)
                ++c[s[j]-'a'][m-j-1];
        }
        for(int i=0;i<26;++i)
            for(int j=0;j<N-1;++j)
                if(c[i][j]>=26)
                {
                    c[i][j+1]+=c[i][j]/26;
                    c[i][j]%=26;
                }
        for(int i=0;i<26;++i) p[i]=i;
        sort(p,p+26,cmp);
        for(int i=25;i>=0;--i) if(!zero[p[i]]) { v[p[i]]=0; break; }
        int cur=25;
        for(int i=0;i<26;++i)
            if(v[p[i]]!=0) v[p[i]]=cur--;
        ll ans=0;
        for(int i=0;i<26;++i)
        {
            ll k=1,res=0;
            for(int j=0;j<N;++j)
            {
                res=(res+k*c[i][j]%mod)%mod;
                k=k*26%mod;
            }
            ans=(ans+v[i]*res%mod)%mod;
        }
        printf("Case #%d: ",T++);
        printf("%I64d\n",ans);
    }
    return 0;
}

C:
树形dp

F:

bu=v 代表一条有向边 (u,v)
根据题目给定的 b 数组可以得到一个仅含环的图 G1
再根据 f(i)=bf(ai) 可以再得到一个图 G2
G2 中的环可以被 G1 中的环置换,且求置换的环必须是被置换的环的因子。
因此处理出每种长度环的数量,然后筛一下就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=1e5+7;
int n,m,p[N];
ll cf[N],cb[N];
bool vis[N];
int main()
{
    int T=1;
    while(~scanf("%d%d",&n,&m))
    {
        memset(cf,0,sizeof(cf));
        memset(cb,0,sizeof(cb));
        for(int i=0;i<n;i++)
        {
            int u;
            scanf("%d",&u);
            p[u]=i;
        }
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;++i)
        {
            if(!vis[i])
            {
                int k=0,u=i;
                while(!vis[u]) ++k,vis[u]=true,u=p[u];
                cf[k]++;
            }
        }
        for(int i=0;i<m;i++)
        {
            int u;
            scanf("%d",&u);
            p[i]=u;
        }
        memset(vis,0,sizeof(vis));
        for(int i=0;i<m;++i)
        {
            if(!vis[i])
            {
                int k=0,u=i;
                while(!vis[u]) ++k,vis[u]=true,u=p[u];
                cb[k]++;
            }
        }
        for(int i=n;i>=1;--i)
        {
            ll k=cb[i];
            for(int j=i*2;j<=n;j+=i)
                cb[j]=(cb[j]+k*i%mod)%mod;
            cb[i]=k*i;
        }
        ll ans=1;
        for(int i=1;i<=n;++i)
            while(cf[i]--) ans=ans*cb[i]%mod;
        printf("Case #%d: %I64d\n",T++,ans);
    }
    return 0;
}

H:
H

K:
打表找规律就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ll n,k;
    int T=1;
    while(~scanf("%I64d%I64d",&n,&k))
    {
        printf("Case #%d: ",T++);
        if(k<=n) printf("%I64d\n",k);
        else
        {
            k-=n;
            if((k-1)/(n-1)%2==0)
            {
                if(k%(n-1)==0) printf("%I64d\n",n-1);
                else printf("%I64d\n",(k-1)%(n-1)+1);
            }
            else
            {
                if(k%(n-1)==0) printf("%I64d\n",n);
                else printf("%I64d\n",(k-1)%(n-1)+1);
            }
        }
    }
}

L:
L

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值