牛客周赛 Round 30

周赛题的链接<---

题目B:  小红的正整数

        大意:小红拿到了一个正整数,她希望你将该正整数重排,使得最终正整数尽可能小。不能包含前导零

做法:这是一首贪心,我们可以使用桶排序,使用string输入,去统计0~9每一个数出现的次数,由于不能包含前导零,我们去找1~9数字个数中第一个不为0的数,输出一个之后再从0~9去遍历每一个数给它输出完。可以证明这是最小

#include<iostream>
using namespace std;
const int N = 11;
int cnt[N];
int main()
{
    string str;cin>>str;
    for(int i=0;i<str.size();i++)cnt[str[i]-'0']++;
    for(int i=1;i<=9;i++)
    {
        if(cnt[i])
        {
            cout<<i;
            cnt[i]--;
            for(int i=0;i<=9;i++)
            {
                while(cnt[i]--)cout<<i;
            }
            return 0;
        }
    }
}

题目C:小红的构造回文

        大意: 小红拿到了一个回文串,她希望你将这个回文串重排,使得重排后仍然是回文串且和原串不同。

做法:输入保证都是回文的字符串,我们可以知道当它的长度小于等于3时就是定不可以(没有可以换的),这也是一个贪心,我们就去遍历它的前半部分,如果都是相等则没有正解输出-1,否则找到不相等的一对就直接交换这一对和后半部分的这一对直接break输出就好

 

#include<iostream>
using namespace std;
int main()
{
    string str;
    cin>>str;
    if(str.size()<=3)
    {
        cout<<-1<<endl;
        return 0;
    }
    int len=str.size()-1;
    for(int i=0;i<len/2-1;i++)
    {
        if(str[i]!=str[i+1])
        {
            swap(str[i],str[i+1]);
            swap(str[len-i],str[len-i-1]);
            cout<<str<<endl;
            return 0;
        }
    }
    cout<<-1<<endl;
    return 0;
}

 题目D:小红整数操作

        大意:给一两个整数x,y你可以进行两个操作1将两个数同时乘以a。2若a即是x的因子,也是y的因子,则将两个数同时除以a。问:小红希望最终两个数都在[l,r]区间内,输出有多少个满足的x的不同的值

做法:这这这是最痛苦的一题就差一点,我默认x是大于y的了没有swap太可惜了,以后题目上没给的都当作没有55555。我认为这也是用到了贪心的思想,想法是先把x,y变成能变成的最小,即都除以它们的最大公因数,然后去找区间【l,r】,我们是进行进来乘除操作折合就是每次加上它们最小的数 。  比如:x是10,y是20,l和r是[2,20]我们先除它们的最大公因数10就变成 1和2了,把这个值记下来,我们可以都乘2,变成2,4是一种,再都除以2变成原来的1,2,然后再都乘3变成3,6.....以次类推我们就能发再不用来回乘除,直接每次加上它们最小的状态就好了,这个题就做出来了

 

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
long long ans;
int main()
{
    long long x,y,l,r;
    cin>>x>>y>>l>>r;
    long long diff;
        diff=__gcd(x,y);
        x/=diff,y/=diff;
        if(x>y)swap(x,y);//真服!!!!!!!!!!!!!!!!!
        diff=ceil(l*1.0/x);
        long long a=x,b=y;
        x*=diff,y*=diff;//直接找到满足的x
        while(x>=l&&y<=r)
        {
            ans++;
            x+=a,y+=b;
        }
    cout<<ans<<endl;
    return 0;
}

题目E:小红树上染色->树形dp,会不了一点 ,很好的一道题,看了代码很容易理解

        大意:有一棵树,初始所有节点都是白色。小红希望染红若干个节点,使得不存在两个白色节点相邻。小红想知道共有多少种方案?答案对MOD取模

#include<iostream>//树上dp
#include<vector>
using namespace std;
const int N = 1e5+10,MOD=1e9+7;
vector<int>g[N];
long long dp[N][2];
//思路:我们定义dp[i][0/1]代表i号节点不染色/染色的子树合法方案数,dfs中使用后序遍历,当子树
//所有信息都被求出来了以后,我们根据当前节点的颜色讨论不同情况的合法方案转移即可
void treedfs(int x,int pre)
{
    dp[x][1]=dp[x][0]=1;
    for(auto i:g[x])
    {
        if(i==pre)continue;
        treedfs(i,x);
        dp[x][0]=dp[x][0]*dp[i][1]%MOD;//父不染,子就必需染
        dp[x][1]=dp[x][1]*(dp[i][0]+dp[i][1])%MOD;//父染,子可染可不染
    }
}

int main()
{
    int n;cin>>n;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    treedfs(1,0);
    cout<<(dp[1][1]+dp[1][0])%MOD;//两种状态的集合
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值