喵哈哈村的魔法考试 Round #20 (Div.2) 题解

时间:2023-03-09 02:46:35
喵哈哈村的魔法考试 Round #20 (Div.2) 题解

题解:

A 喵哈哈村的跳棋比赛

题解:其实我们要理解题意就好了,画画图看看这个题意。x<y,那么就交换;x>y,那么x=x%y。

如果我们经过很多次,或者y<=0了,那么就会无限循环。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; long long x,y; void work(){
while(1){
if(x==0){
cout<<y<<endl;
break;
}
if(x<y)swap(x,y);
if(x==0){
cout<<y<<endl;
break;
}
if((y<=0)&&(x>y)){
cout<<"N/A\n";
break;
}
x%=y;
}
} int main(){
while(cin>>x>>y)work();
return 0;
}

喵哈哈村的扔骰子大赛

题解:暴力dfs就可以,dfs(i,j),i是当前扔到第j个骰子,j表示当前和的组合,我们把组合用状态压缩表示一下。你本地打表其实也可以

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int ans=0;
inline int Gcd(int a,int b){return b?Gcd(b,(a%b)):a;}
void go(int v,long long lop){
if(v>n){
if(lop&((long long)1<<(long long)m)) ans++;
return;
}
for(int i=1;i<=6;i++)
go(v+1,lop|(lop<<i));
}
int main(){
scanf("%d%d",&n,&m);
go(1,1);
int d=1;
for(int i=1;i<=n;i++)d*=6;
if(ans==0) printf("0\n");
else if(ans==d) printf("1\n");
else{
int gc=Gcd(ans,d); printf("%d/%d",ans/gc,d/gc);
}
}

喵哈哈村的魔方大赛

题解:最多转两次,暴力模拟一下吧

#include <iostream>
#include <algorithm>
using namespace std;
int F(char f)
{
switch(f)
{
case 'U':
return 0;
case 'D':
return 1;
case 'L':
return 2;
case 'R':
return 3;
case 'F':
return 4;
case 'B':
return 5;
}
}
int k[9][6] = {
{0, 1, 5, 4, 2, 3},
{0, 1, 3, 2, 5, 4},
{0, 1, 4, 5, 3, 2},
{5, 4, 2, 3, 0, 1},
{1, 0, 2, 3, 5, 4},
{4, 5, 2, 3, 1, 0},
{3, 2, 0, 1, 4, 5},
{1, 0, 3, 2, 4, 5},
{2, 3, 1, 0, 4, 5}
};
int main()
{
int n, x1, y1, z1, x2, y2, z2, fa1, fa2;
char f1, f2;
cin >> n >> x1 >> y1 >> z1 >> f1 >> x2 >> y2 >> z2 >> f2;
fa1 = F(f1);
fa2 = F(f2);
if (x1 == x2 && y1 == y2 && z1 == z2 && fa1 == fa2)
cout << 0;
else if (
x1 == z2 && y1 == y2 && z1 == n + 1 - x2 && fa1 == k[0][fa2] ||
x1 == n + 1 - x2 && y1 == y2 && z1 == n + 1 - z2 && fa1 == k[1][fa2] ||
x1 == n + 1 - z2 && y1 == y2 && z1 == x2 && fa1 == k[2][fa2] ||
x1 == x2 && y1 == n + 1 - z2 && z1 == y2 && fa1 == k[3][fa2] ||
x1 == x2 && y1 == n + 1 - y2 && z1 == n + 1 - z2 && fa1 == k[4][fa2] ||
x1 == x2 && y1 == z2 && z1 == n + 1 - y2 && fa1 == k[5][fa2] ||
x1 == y2 && y1 == n + 1 - x2 && z1 == z2 && fa1 == k[6][fa2] ||
x1 == n + 1 - x2 && y1 == n + 1 - y2 && z1 == z2 && fa1 == k[7][fa2] ||
x1 == n + 1 - y2 && y1 == x2 && z1 == z2 && fa1 == k[8][fa2]
)
cout << 1;
else
{
if (x1 > (1 + n) / 2)
x1 = n + 1 - x1;
if (x2 > (1 + n) / 2)
x2 = n + 1 - x2;
if (y1 > (1 + n) / 2)
y1 = n + 1 - y1;
if (y2 > (1 + n) / 2)
y2 = n + 1 - y2;
if (z1 > (1 + n) / 2)
z1 = n + 1 - z1;
if (z2 > (1 + n) / 2)
z2 = n + 1 - z2;
if (x1 > y1)
swap(x1, y1);
if (x1 > z1)
swap(x1, z1);
if (y1 > z1)
swap(y1, z1);
if (x2 > y2)
swap(x2, y2);
if (x2 > z2)
swap(x2, z2);
if (y2 > z2)
swap(y2, z2);
if (x1 == x2 && y1 == y2 && z1 == z2)
cout << 2;
else
cout << -1;
}
return 0;
}

喵哈哈村的种树大赛

题解:简单的线段树的区间更新,区间求gcd的题。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; int n,m,M;
int Tree[1048576<<2],tree[1048576]; inline int gcd(int x,int y)
{
x=x<0?-x:x; y=y<0?-y:y;
for (int r;y;r=x%y,x=y,y=r);
return x;
} int main()
{
scanf("%d%d",&n,&m);
for(M=1;M<=n+1;M<<=1);
while(m--)
{
int opt;
scanf("%d",&opt);
if(opt==1)
{
int l,r,t;
scanf("%d%d%d",&l,&r,&t);
for(int x=l;x<=n;x+=x&(-x))tree[x]+=t;
for(int x=r+1;x<=n;x+=x&(-x))tree[x]-=t;
Tree[l+=M]+=t;
for(int x=(l>>1);x;x>>=1)Tree[x]=gcd(Tree[x<<1],Tree[(x<<1)|1]);
Tree[r+=M+1]-=t;
for(int x=(r>>1);x;x>>=1)Tree[x]=gcd(Tree[x<<1],Tree[(x<<1)|1]);
}else
{
int l,r;
scanf("%d%d",&l,&r);
int ret=0,tmp=0;
for(int x=l+M,y=r+M+1;x^y^1;x>>=1,y>>=1)
{
if(!(x&1))ret=gcd(ret,Tree[x^1]);
if(y&1)ret=gcd(ret,Tree[y^1]);
}
for(int x=l;x;x-=x&(-x))tmp+=tree[x];
ret=gcd(ret,tmp);
printf("%d\n",ret);
}
}
}

喵哈哈村的玩手机大赛

题解:最大流,A-手机-B就好了,但是暴力连图是会挂的,所以我们倍增优化一下连接的正方形就好(x

代码:

#include<cstdio>
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
const int N=56010,inf=~0U>>2;
int n,S,T,h[N],gap[N],maxflow;
struct edge{int t,f;edge *nxt,*pair;}*g[N],*d[N];
int r,c,a,b,x1,x2,y1,y2,w;
int i,j,k,fs[62][62][6],ft[62][62][6],pow[8],log[62];
inline int min(int a,int b){return a<b?a:b;}
inline void add(int s,int t,int f){
edge *p=new(edge);p->t=t;p->f=f;p->nxt=g[s];g[s]=p;
p=new(edge);p->t=s;p->f=0;p->nxt=g[t];
g[t]=p;g[s]->pair=g[t];g[t]->pair=g[s];
}
int sap(int v,int flow){
if(v==T)return flow;
int rec=0;
for(edge *p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
int ret=sap(p->t,min(flow-rec,p->f));
p->f-=ret;p->pair->f+=ret;d[v]=p;
if((rec+=ret)==flow)return flow;
}
d[v]=g[v];
if(!(--gap[h[v]]))h[S]=T;
gap[++h[v]]++;
return rec;
}
int main(){
for(pow[0]=i=1;i<8;i++)pow[i]=pow[i-1]<<1;
for(i=1;i<62;i++)for(j=i;j>1;j>>=1,log[i]++);
read(r);read(c);read(a);read(b);
for(i=1;i<=r;i++)for(j=1;j<=c;j++){
fs[i][j][0]=++n,ft[i][j][0]=++n;
read(k);
add(fs[i][j][0],ft[i][j][0],k);
}
for(k=1;k<6;k++)for(i=1;i<=r;i++)for(j=1;j<=c;j++)if(i+pow[k]-1<=r&&j+pow[k]-1<=c){
fs[i][j][k]=++n,ft[i][j][k]=++n;
add(fs[i][j][k],fs[i][j][k-1],inf),add(ft[i][j][k-1],ft[i][j][k],inf);
add(fs[i][j][k],fs[i+pow[k-1]][j][k-1],inf),add(ft[i+pow[k-1]][j][k-1],ft[i][j][k],inf);
add(fs[i][j][k],fs[i][j+pow[k-1]][k-1],inf),add(ft[i][j+pow[k-1]][k-1],ft[i][j][k],inf);
add(fs[i][j][k],fs[i+pow[k-1]][j+pow[k-1]][k-1],inf),add(ft[i+pow[k-1]][j+pow[k-1]][k-1],ft[i][j][k],inf);
}
S=n+a+b+1;T=S+1;
while(a--){
read(w),read(x1),read(y1),read(x2),read(y2);
add(S,i=++n,w);
k=log[j=x2-x1+1];
add(i,fs[x1][y1][k],inf);
add(i,fs[x1][y2-pow[k]+1][k],inf);
add(i,fs[x2-pow[k]+1][y1][k],inf);
add(i,fs[x2-pow[k]+1][y2-pow[k]+1][k],inf);
}
while(b--){
read(w),read(x1),read(y1),read(x2),read(y2);
add(i=++n,T,w);
k=log[j=x2-x1+1];
add(ft[x1][y1][k],i,inf);
add(ft[x1][y2-pow[k]+1][k],i,inf);
add(ft[x2-pow[k]+1][y1][k],i,inf);
add(ft[x2-pow[k]+1][y2-pow[k]+1][k],i,inf);
}
gap[0]=T;
for(i=0;i++<T;)d[i]=g[i];
while(h[S]<T)maxflow+=sap(S,inf);
printf("%d",maxflow);
return 0;
}