喵哈哈村的魔法考试 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;
}

转载于:https://www.cnblogs.com/qscqesze/p/6862281.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值