周赛题的链接<---
题目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;
}