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'组成的字符串,但其中的一些字符被替换成了'?'。游游已经不记得原串是什么样子了,但她还记得该字符串有以下性质:
字符串的相邻的字符都是不相等的。
字符串的所有长度为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这种了。