1.1594D - The Number of Imposters(简单遍历图)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5;
string s1="imposter",s2="crewmate";
int t,n,m,k,f,ans,p1,p2,a[maxn],vis[maxn],to[maxn],head[maxn],w[maxn],nex[maxn];
void add(int x,int y,int z){
to[++k]=y;
nex[k]=head[x];
head[x]=k;
w[k]=z;
}
void dfs(int x){
vis[x]=1;
for(int i=head[x];i;i=nex[i]){
int y=to[i];
if(vis[y]){
if(a[y]!=w[i]^a[x])f=1;
continue;
}
a[y]=a[x]^w[i];
if(!vis[y]){
if(a[y])p1++;
else p2++;
}
dfs(y);
}
}
int main(){
scanf("%d",&t);
while(t--){
f=k=ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)head[i]=vis[i]=0;
for(int i=1,x,y,d;i<=m;i++){
string z;
cin>>x>>y>>z;
if(z==s1)d=1;
else d=0;
add(x,y,d);
add(y,x,d);
}
for(int i=1;i<=n;i++){
if(!vis[i]){
p1=0,p2=1;
a[i]=0;
dfs(i);
ans+=max(p1,p2);
}
}
if(f)printf("-1\n");
else printf("%d\n",ans);
}
}
2.C. Bakry and Partitioning(异或思维+简单树遍历)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=2e6+5;
int t,n,k,f;
ll sum,tot,a[maxn];
vector<int>mp[maxn];
void dfs(int x,int fa){
for(auto y:mp[x]){
if(y==fa)continue;
dfs(y,x);
a[x]^=a[y];
}
if(a[x]==sum){
a[x]=0;
tot++;
}
}
int main(){
scanf("%d",&t);
while(t--){
tot=sum=f=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum^=a[i];
mp[i].clear();
}
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
if(sum==0)f=1;
else if(k>=3)dfs(1,0);
if(tot>=3)f=1;
if(f)printf("YES\n");
else printf("NO\n");
}
}
3.F. Array Stabilization (AND version)(思维考虑专业对象)
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=2e6+5;
int t,n,d,a[maxn];
struct node{
int x,dep;
};
queue<node>p;
int main(){
scanf("%d",&t);
while(t--){
int f=0,ans=0;
scanf("%d%d",&n,&d);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
if(a[i]==0)p.push({i,0});
}
while(!p.empty()){
int x=p.front().x,dep=p.front().dep;
p.pop();
int y=(x+d)%n;
if(a[y]){
a[y]=0;
p.push({y,dep+1});
ans=max(ans,dep+1);
}
}
for(int i=0;i<n;i++)
if(a[i])f=1;
if(f)printf("-1\n");
else printf("%d\n",ans);
}
}
4.E. Permutation Shift(排列交换)
证明
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=2e6+5;
int t,n,m,k,e1[maxn],e2[maxn],vis[maxn],b[maxn],p[maxn],ans[maxn],nex[maxn];
vector<int>mp[maxn];
void dfs(int x){
vis[x]=1;
for(auto y:mp[x]){
if(!vis[y])dfs(y);
}
}
bool check(int x){
int res=0;
for(int i=0;i<n;i++){
mp[i].clear();
vis[i]=0;
}
for(int i=0;i<n;i++){
nex[(i+x)%n]=i;
}
for(int i=0;i<n;i++){
mp[nex[i]].push_back(b[i]);
mp[b[i]].push_back(nex[i]);
}
for(int i=0;i<n;i++){
if(!vis[i])dfs(i),res++;
}
return n-res<=m;
}
int main(){
scanf("%d",&t);
while(t--){
k=0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
p[--b[i]]=i;
e1[i]=e2[i]=0;
}
for(int i=0;i<n;i++){
int d=(p[i]-i+n)%n;
e1[d]++;
}
for(int i=0;i<n;i++){
if(e1[i]*3>=n)e2[i]=1;
}
for(int i=n-1;i>=0;i--){
if(e2[i]){
if(check(i))ans[++k]=i;
if(k==3)break;
}
}
printf("%d",k);
for(int i=k;i;i--){
printf(" %d",ans[i]);
}
printf("\n");
}
}
5.D. Array Differentiation
题意:给出数组a[n],问能否构造数组b,使得ai=bj-bk (n<=10)
思路:
显然对每一对bj-bk连一条权值为ai的边,一定可以构成n个点n条边的有环图。对于环上权值ai,一定可以通过给ai带上正负号求和为0,ai符号为{1,-1,0}
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int t,n,a[maxn];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int s=pow(3,n)-1,f=0;
for(int i=1;i<=s;i++){
int d=i,sum=0;
for(int j=1;j<=n;j++){
int p=d%3;
if(p==1)sum+=a[j];
else if(p==2)sum-=a[j];
d/=3;
}
if(sum==0){
f=1;
break;
}
}
if(f)printf("YES\n");
else printf("NO\n");
}
}
B. Strange Definition(分解质因子+思维)
给出
n
n
n个数,若
l
c
m
(
x
,
y
)
g
c
d
(
x
,
y
)
\frac{lcm(x,y)}{gcd(x,y)}
gcd(x,y)lcm(x,y) 为完全平方数称
x
,
y
x , y
x,y是相邻的
每一秒都会发生以下的情况:
每个数被所有和自己相邻数字(包括自己)的乘积所替换
设为
d
i
d_i
di和数字
a
i
a_i
ai相邻数字的数量
给出
q
q
q组询问,问第
i
i
i秒最大的
d
i
d_i
di
思路:
由于lcm(x,y)=x*y/gcd(x,y)
所以只要x∗y是完全平方数即可
如果xy是完全平方数,xz是完全平方数
那么yz是完全平方数,又因为x^2是完全平方数
那么y z也是完全平方数
所以相邻的元素都是彼此相邻的,可以分成若干个组
而x,y相邻的条件是对应的质因子质数奇偶性相同
那么可以质因子分解,保存对应的奇偶性作为分组的依据,使用map装起来
那么考虑每秒的变化,组内的数乘起来
如果组内的数个数为奇数,那么不会改变每个质因子的奇偶性质,分组不变
如果组内的数个数为偶数,一次变化过后所有的幂都变成了偶数,每个数都是完全平方数
一秒后,所有偶数组的个数都合并了
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=1e6+5;
int t,n,cnt,q,vis[maxn],prime[maxn],a[maxn];
void getprime(){
for(int i=2;i<=1e6;i++){
if(!vis[i])prime[++cnt]=i;
for(int j=1;j<=cnt&&i*prime[j]<=1e6;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
int main(){
getprime();
scanf("%d",&t);
while(t--){
scanf("%d",&n);
a[n+1]=0;
for(int i=1,x;i<=n;i++){
a[i]=1;
scanf("%d",&x);
int d=1;
if(!vis[x])a[i]=x;
else{
for(int j=1;j<=cnt;j++){
if(x%prime[j]==0){
int he=0;
while(x%prime[j]==0){
x/=prime[j];
he++;
}
if(he%2)a[i]*=prime[j];
}
if(x<1ll*prime[j]*prime[j])break;
}
if(x!=1)a[i]*=x;
}
}
sort(a+1,a+1+n);
int he=1,p1=0,p0=0,p2=0,k=0;
for(int i=2;i<=n+1;i++){
if(a[i]==a[i-1])he++;
else {
if(a[i-1]==1)p0=he;
else if(he%2)p1=max(p1,he);
else p2+=he,p1=max(he,p1);
he=1;
}
}
scanf("%d",&q);
while(q--){
ll x;
scanf("%lld",&x);
if(x==0)printf("%d\n",max(p0,p1));
else printf("%d\n",max(p0+p2,p1));
}
}
}