牛客周赛 Round 15

A、

题目描述

游游拿到了一个正整数,她希望将它切割成两部分,使得它们的和为偶数。游游想知道有多少种合法的切割方案?
注:切割后的正整数允许出现前导零。

输入描述:

一个正整数,大小不超过10^100000

输出描述:

一个整数,代表切割的方案数。

示例1

输入

103

输出

1

说明

切割成1+03=4是合法的,但10+3=13为奇数,不符合要求。所以有1种合法方案。

 思路:两部分,其中有一部分最后一位肯定是固定的。枚举就行

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define fp(i,a,b) for(int i=a;i<=b;++i)
#define PII pair<int,int>
const int N=1e5+10;
const int mod=1e9+7;
const double eps=1e-5;
typedef double db;
int n;
int qsm(int x,int n)
{
	int res=1;
	while(n)
	{
		if(n&1)res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	} 
	return res;
}
void solve()
{
   ; 
}
string s;
int sum=0;
signed main()
{
	cin>>s;
	int sz=s.size();
	int f=s[sz-1]-'0';
	for(int i=0;i<sz-1;i++)
	{
		int x=s[i]-'0';
		if((x+f)&1){
			;
		}
		else sum++;
	}
	cout<<sum<<"\n";
	
	return 0;
} 





B、

题目描述

对于一个小写字母而言,游游可以通过一次操作把这个字母变成相邻的字母。'a'和'b'相邻,'b'和'c'相邻,以此类推。特殊的,'a'和'z'也是相邻的。可以认为,小写字母的相邻规则为一个环。

游游拿到了一个仅包含小写字母的字符串,她想知道,使得所有字母都相等至少要多少次操作?

输入描述:

 
 

一个仅包含小写字母,长度不超过100000的字符串。

输出描述:

 
 

一个整数,代表最小的操作次数。

示例1

输入

yab

输出

3

说明

 
 

第一次操作,把'y'变成'z',字符串变成了"zab"

第二次操作,把'b'变成'a',字符串变成了"zaa"

第三次操作,把'z'变成'a',字符串变成了"aaa"

 

思路:枚举要变成哪一个字符就行

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define fp(i,a,b) for(int i=a;i<=b;++i)
#define PII pair<int,int>
const int N=1e5+10;
const int mod=1e9+7;
const double eps=1e-5;
typedef double db;
int n;
int qsm(int x,int n)
{
	int res=1;
	while(n)
	{
		if(n&1)res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	} 
	return res;
}
void solve()
{
   ; 
}
string s;
int sum=0;
int mmin=1e18;
signed main()
{
	cin>>s;
	int sz=s.size();
	
	for(int i=0;i<=25;i++)
	{
		int sum=0;
		char c='a'+i;
		for(int j=0;j<sz;j++)
		{
			int f=min(abs(s[j]-c),26-abs(s[j]-c));
			sum+=f;
		}
		mmin=min(mmin,sum);
	}
	cout<<mmin<<"\n";
	
	
	return 0;
} 





 C、


题目描述

游游有一个仅由'0'、'1'、'2'组成的字符串,但其中的一些字符被替换成了'?'。游游已经不记得原串是什么样子了,但她还记得该字符串有以下性质:

1. 字符串的相邻的字符都是不相等的。

2. 字符串的所有长度为3的连续子串,代表的三进制数的数值都是偶数。

游游希望你帮忙还原该串,你能帮帮她吗?

输入描述:

一个仅由'0'、'1'、'2'和'?'组成的字符串。'?'字符代表未知字符。
字符串长度不超过1000。
对于50%的数据,'?'字符的数量不超过2个。对于其余数据则无以上限制。

输出描述:

 
 

如果没有合法的解,则说明游游记错了,请输出-1。

否则输出一个合法的字符串。有多解时输出任意即可。

示例1

输入

1?1

输出

121

说明

 
 

121作为三进制数,其数值为16,为偶数。

输出101也是合法的。

示例2

输入

0??2

输出

0202

说明

 
 

020代表的三进制数为6,202代表的三进制数为20,都是偶数。且字符串没有两个相邻字符相等。

示例3

输入

11?

输出

-1

说明

 
 

由于已经有1和1相邻且相等,所以无解。

其实size>=4的时候 就不可能有1了。应该是个找规律的题目

#include<iostream>
#include<string>
using namespace std;
bool is(string s,string t){
    if(s.size()!=t.size())return false;
    for(int i=0;i<s.size();i++)
        if(s[i]!=t[i]&&s[i]!='?')
            return false;
    return true;
}
int main(){
    string s,t="",tt="";
    cin>>s;
    
    for(int i=0;i<s.size();i++)t+=char('0'+2*(i%2)),tt+=('0'+2*((i+1)%2));
    
    
    if(is(s,"101"))
        cout<<"101"<<endl;
    else if(is(s,"121"))
        cout<<"121"<<endl;
    else if(is(s,"1"))
        cout<<"1"<<endl;
    else if(is(s,"2"))
        cout<<"2"<<endl;
    else if(is(s,"0"))
        cout<<"0"<<endl;
    else if(is(s,"12"))
        cout<<"12"<<endl;
    else if(is(s,"10"))
        cout<<"10"<<endl;
    else if(is(s,"01"))
        cout<<"01"<<endl;
    else if(is(s,"21"))
        cout<<"21"<<endl;
    else if(is(s,"02"))
        cout<<"02"<<endl;
    else if(is(s,"20"))
        cout<<"20"<<endl;
    else if(is(s,t))
        cout<<t<<endl;
    else if(is(s,tt))
        cout<<tt<<endl;
    else
        cout<<-1<<endl;
    //cout<<t<<" "<<tt<<endl;
}

D、


题目描述

游游拿到了一棵树,树的每条边有边权。

游游准备选择一些边染成红色,她希望不存在两条染红的边共用同一个点,且最终染红边的权值之和尽可能大。你能帮帮她吗?

注:所谓树,即不包含重边、自环和回路的无向连通图。

输入描述:

第一行输入一个正整数n。代表节点的数量。

接下来的n−1n-1n−1行,每行输入三个正整数u,v,w,代表点u和点v之间有一条权值为w的无向边。

1≤n≤10^5
1≤u,v≤n
1≤w≤10^9

输出描述:

一个正整数,代表最终染红的边的权值之和的最大值。

示例1

输入

5
1 2 2
2 3 5
3 4 4
3 5 3

输出

6

说明

 
 

将点1和点2、点3和点4的边染红

 

 

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define fp(i,a,b) for(int i=a;i<=b;++i)
#define PII pair<int,int>
const int N=2e5+10;
const int mod=1e9+7;
const double eps=1e-5;
typedef double db;
int n;
int e[N],ne[N],w[N],h[N],idx;
void add(int x,int y,int z)
{
	e[idx]=y;
	ne[idx]=h[x];
    w[idx]=z;
    h[x]=idx++;
}
int dp[N][2];
void dfs(int x,int fa)
{
//	cout<<x<<" "<<fa<<"\n";
	int mmax=0;
	for(int i=h[x];~i;i=ne[i])
	{
		int j=e[i];
		if(j==fa)continue;
		dfs(j,x);
		dp[x][0]+=max(dp[j][0],dp[j][1]);
		dp[x][1]=max(dp[x][1],w[i]+dp[j][0]);
	}
//	cout<<x<<" "<<dp[x][0]<<" "<<dp[x][1]<<"\n";
}
signed main()
{
    cin>>n;
	
	memset(h,-1,sizeof h);
	
	fp(i,1,n-1)
	{
	   int a,b,c;
	   cin>>a>>b>>c;
	   add(a,b,c);
	   add(b,a,c);	
	}	
	dfs(1,-1);
	cout<<max(dp[1][0],dp[1][1]);
	return 0;
} 
//dp[fa][0] 不选与子节点的边 




 这是我最一开始的代码。

dp[x][0] 我不要x与子节点j的边 那我加上所有max(dp[j][0],dp[j][1])就行了

dp[x][1]我要x与子节点j的边+dp[j][0]

但是其他的子节点dp[j][1]我没有算。感觉得求个sum?

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define fp(i,a,b) for(int i=a;i<=b;++i)
#define PII pair<int,int>
const int N=2e5+10;
const int mod=1e9+7;
const double eps=1e-5;
typedef double db;
int n;
int e[N],ne[N],w[N],h[N],idx;
void add(int x,int y,int z)
{
	e[idx]=y;
	ne[idx]=h[x];
    w[idx]=z;
    h[x]=idx++;
}
int dp[N][2];
void dfs(int x,int fa)
{
	for(int i=h[x];~i;i=ne[i])
	{
		int j=e[i];
		if(j==fa)continue;
		dfs(j,x);
		dp[x][0]+=max(dp[j][0],dp[j][1]);
	}
	for(int i=h[x];~i;i=ne[i])
	{
		int j=e[i];
		if(j==fa)continue;
		dp[x][1]=max(dp[x][1],dp[x][0]-max(dp[j][0],dp[j][1])+dp[j][0]+w[i]);
	}
}
signed main()
{
    cin>>n;
	
	memset(h,-1,sizeof h);
	
	fp(i,1,n-1)
	{
	   int a,b,c;
	   cin>>a>>b>>c;
	   add(a,b,c);
	   add(b,a,c);	
	}	
	dfs(1,-1);
	cout<<max(dp[1][0],dp[1][1]);
	return 0;
} 
/*
9
1 2 4
1 7 4
1 4 5
2 8 7
2 5 7
4 3 11
3 9 123
4 6 33
*/




后来的代码就是利用dp[x][0]让这个子节点j的恢复 这样就不用求sum这种了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值