1004 Black Magic
给出n个方块,每个方块的左/右都可能是黑或白。将这些方块排成一列,如果两个相邻方块相连接的面都是黑色,那么这两个方块会连在一起。求连通块的最大/最小数量。(n<=10^5)
分类讨论,以下的L,R,E,B含义和题目中一样。对于连通块最多的情况,要让能够相连的方块对尽量少。可以发现,所有L可以全放在最左边,所有R可以全放在最右边,这样他们就不会和中间的方块相连,之后尽可能用E把B隔开即可。对于连通块最少的情况,要让能够相连的方块对尽可能多。可以先把所有B拼在一起,之后可以把一个L和一个R分为一组拼起来。注意如果有至少一组LR并且也有至少一块B的话,可以把一组LR拆开拼在B的两边,这样可以再减少一个连通块。
#include<bits/stdc++.h>
using namespace std;
template <typename tn>void read(tn &n){
tn f=1,t=0;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) t=t*10+ch-'0',ch=getchar();
n=f*t;
}
inline void out(int x){
if(x>9)out(x/10);
putchar(x%10+'0');
}
int T,E,L,L2,R,R2,B,Ans;
int main(){
read(T);
while(T--){
read(E),read(L),read(R),read(B);
L2=L,R2=R,Ans=0;
int com=min(L,R);
if(com==0){
Ans=E+L+R;
if(Ans==E&&B>0)Ans++;
}else{
Ans=E+com;
L-=com,R-=com;
Ans+=L+R;
}
cout<<Ans<<" ";
L=L2,R=R2;
if(B==0)Ans=E+L+R;
else{
B-=1;
Ans=L+R+1;
if(B>=E)Ans+=2*E;
else Ans+=E+B;
}
cout<<Ans<<endl;
}
return 0;
}
1008 Triangle Game
一个非退化三角形,三边边长分别为a,b,c。现
Kate
和
Emilico 二人做游戏,每轮需要令三角形的一边长度减去一正整数,使这个三角形退化的一方负。
Kate
先手,双方均采用最优策略,问
Kate
是否会获胜。
结论是:
Kate
获胜当且仅(a-1)^(b-1)^(c-1)不为0时
#include<bits/stdc++.h>
using namespace std;
template <typename tn>void read(tn &n){
tn f=1,t=0;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) t=t*10+ch-'0',ch=getchar();
n=f*t;
}
inline void out(int x){
if(x>9)out(x/10);
putchar(x%10+'0');
}
int T;
long long a,b,c,d;
int main(){
read(T);
while(T--){
read(a),read(b),read(c);
a--,b--,c--;
d=((a^b)^c);
if(d)cout<<"Win"<<endl;
else cout<<"Lose"<<endl;
}
return 0;
}
1003 Counting Stickmen
给定一棵树,求其中有多少个人
为了方便描述
,
姑且将火柴人划分为头
, 手臂2个,手掌2个,
身体
, 腿2个的8条边
.
对于一个火柴人
,
我们枚举中间身体的那条边进行计数
假设身体靠头一侧的端点为x
,
靠腿一侧的端点为y
, 我们在x处计算头和手的方案,
在y处计算腿的方案
,
根据乘法原理
,
相乘即可得到火柴人的种数
#include<bits/stdc++.h>
using namespace std;
#define gc c=getchar()
#define r(x) read(x)
#define ll long long
template <typename tn>void read(tn &n){
tn f=1,t=0;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) t=t*10+ch-'0',ch=getchar();
n=f*t;
}
inline void out(int x){
if(x>9)out(x/10);
putchar(x%10+'0');
}
const int N=1e7+7;
const int p=998244353;
vector<int>G[N];
int deg[N],s0[N],s1[N],s2[N];
inline int add(int a,int b){
return (a+=b)>=p?a-p:a;
}
inline int sub(int a,int b){
return (a-=b)<0?a+p:a;
}
inline ll calc(int x){
return (ll)x*(x-1)/2%p;
}
int main(){
int T;
r(T);
while(T--){
int n;
r(n);
for(int i=1;i<=n;++i)G[i].clear(),deg[i]=s0[i]=s1[i]=s2[i]=0;
for(int i=1;i<n;++i){
int u,v;r(u),r(v);
G[u].push_back(v);
G[v].push_back(u);
++deg[u],++deg[v];
}
for(int x=1;x<=n;++x){
s0[x]=deg[x];
for(auto &y:G[x]){
s1[x]=add(s1[x],deg[y]-1);
s2[x]=add(s2[x],calc(deg[y]-1));
}
}
int ans=0;
for(int x=1;x<=n;++x){
if(s0[x]>=4){
for(auto &y:G[x]){
if(s0[y]>=3){
int head=sub(s0[x],3);
int foot=sub(s0[y],1);
int hand=sub(s1[x],foot);
ans=add(ans,(ll)head*sub(calc(hand),sub(s2[x],calc(deg[y]-1)))%p*calc(foot)%p);
}
}
}
}
printf("%d\n",ans);
}
return 0;
}