1.特别的玛格丽特
每次可以交换数组中两个奇数或者两个偶数,
可以交换无数次。
思路:
分别用a,b记录下奇数和偶数的个数,当为第偶数个数字时,
如果此时奇数个数不等于偶数个数,就不行。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int x,n,a,b;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(x&1) a++;
else b++;
if(i%2==0){
if(a!=b){
puts("No");
return 0;
}
}
}
puts("Yes");
return 0;
}
2.野比大雄的作业
思路:
ans=[l,r]区间内所有数字的与运算的和+或运算的和,
输出ans的最大值。
尽量使[l,r]区间内的与运算和为1同时或运算和为1,
因为
&:都1为1,有0为0
|:有1为1,全0为0
因为题目没说不能为1个数,
所以能够满足题目要求的区间一定只是一个数[l,l],
即 x&x+x|x=x+x最大,
又因为x+x=x<<1,所以就是找这个数组里最大的数再*2
AC代码:
(1)C++:
#include <bits/stdc++.h>
using namespace std;
int x,ans,n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
if((x<<1)>ans) ans=(x<<1);
}
printf("%d\n",ans);
return 0;
}
(2)Python:
input() #输入n
print(max(map(int,input().split())) * 2) #输入,以空格为分隔符,寻找输入的最大值,再将最大值*2
3.哦唔西迪西小姐
唔西迪西现在正处在一个冰火迷宫中,迷宫由 n
个格子组成,每个格子要么是冰之格,要么是火之格,唔西迪西刚开始可以选择从迷宫中任意一个开始走,走到第 iii 个位置时会得到值为
ai的积分。(注意:唔西迪西也可以选择一个格子都不走)如果唔西迪西当前在冰之格,那么她可以选择一个编号大于当前格子的冰之格,跳到那里。如果唔西迪西当前在火之格,那么她可以选择一个编号大于当前格子的火之格,跳到那里。如果唔西迪西目前没有格子可以走,那么结束。同时,即使存在可以跳过去的格子,唔西迪西也可以选择在任意时刻结束。
唔西迪西想最大化她的得分,于是她学会了一个超能力,她能在比赛开始的时候改变最多 m
个格子的状态,即将一个格子从冰之格变成火之格或从火之格变成冰之格,改变第 i 个格子的状态会让唔西迪西的得分减少 pi
。(唔西迪西改变格子的状态后才开始挑选起点开始行动,也就是说,得分分成两部分,一部分是改变格子状态的得分,一部分是走格子的得分)
你能告诉唔西迪西她最多得几分吗
思路:
优先队列。
每一种格子有0/1两种状态,因为a[i]和p[i]都可能为负,
因此状态一致时可以选择走或者不走(a[i]为负时肯定选择不走啊!),
状态不一致时利用优先队列,选出>0的前m个就行了。
最后从状态0/1中选择最大的即可。
具体来说,
当状态一致时,可以有选或不选两种状态,当a[i]为负时,不选。
但是由于p[i]可能为负,等会-p[i]可能会大于a[i],这样反而会赚,
因此把-p[i]-max(0,a[i])加入队列。
状态不一致时,有选或不选两种情况。
不选的话:-p[i]
选的话:a[i]-p[i]
选择这两种的最大值加入队列。
最后在状态为0和状态为1之间选择最大值。
注意结果可能为ll,所以函数get的返回值应该为ll。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
int n,m,a[N],p[N],b[N];
ll get(int x){
ll sum=0;
priority_queue<int> q;
for(int i=1;i<=n;i++){
if(b[i]==x){
sum+=max(0,a[i]);//>0时才走,小于0时不走
//因为p[i]可能为负,因此可能-p[i]>a[i],此时改变这个状态可能会赚,
q.push(-p[i]-max(0,a[i]));//所以把-p[i]-max(0,a[i])加入队列
}
else{//状态不一致时,也有选或者不选两种,不选:-p[i],选:a[i]-p[i]
q.push(max(-p[i],a[i]-p[i]));
}
}
int cnt=0;
while(q.size()){//取出前m大的
auto x=q.top();
q.pop();
if(cnt+1>m) break;//已经选完了前m个
if(x<=0) break;//都已经为负数了,肯定不选啊!后面也都为负数,结束!
sum+=x;
cnt++;
}
return sum;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
cout<<max(get(0),get(1));
return 0;
}
4.月之暗面
给出一棵 n个点的树,有 x 种普通颜色,y 种特殊颜色
现在要给树上的每个节点染色,普通颜色染色没有限制,但两个相邻的节点不能染相同颜色的特殊颜色
求染色方案数,答案对 998244353 取模。
思路:
树:n个节点。x种普通颜色,y种特殊颜色。
相邻两点不能为相同的特殊颜色。
树形dp;
dp[u][0]:表示父节点u取普通颜色,那么子节点颜色无限制。
则dp[u][0]*=(dp[v][0]*x+dp[v][1]y);
dp[u][1]:表示父节点取特殊颜色,那么子节点可以取普通颜色,
取特殊颜色时只能取y-1种啦,
则dp[u][1]=(dp[v][0]x+dp[v][1](y-1));
最后答案就是(dp[1][0]*x%mod+dp[1][1]*y%mod )%mod;
一定要用ll,并且不要乱用x!
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353 ;
const int N = 1e6+10;
ll dp[N][2],x,y;
int n;
vector<int> e[N];
void dfs(int u,int fa){
dp[u][0]=dp[u][1]=1ll;//初始化均为1
for(auto v:e[u]){//孩子们
if(v==fa) continue;//x的儿子肯定不能为x的父节点啊
dfs(v,u);//继续搜,此时x为它的父节点
//对于每个节点,方案数为子节点方案数的乘积
//x涂普通颜色
dp[u][0]=dp[u][0]*(dp[v][0]*x%mod+dp[v][1]*y%mod)%mod;
//x涂特殊颜色
dp[u][1]=dp[u][1]*(dp[v][0]*x%mod+dp[v][1]*(y-1)%mod)%mod;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
scanf("%d %lld %lld",&n,&x,&y);
for(int i=1;i<=n-1;i++){
int a,b;
scanf("%d %d",&a,&b);
//建边
e[a].push_back(b);
e[b].push_back(a);
}
dfs(1,0);//从1开始搜,其父节点假设为0
cout<<(dp[1][0]*x%mod+dp[1][1]*y%mod)%mod;
return 0;
}