10月17日考试 题解(位运算+状压DP+打表+大模拟)

T1 神奇的位运算

题目大意:给定$n$个长度为$m$的$01$串,每一位都有一种位运算,为与(&),或(|),异或(^)的一种。现为了确定每一位的位运算的种类,问最少添加多少字符串。

可以发现每一位都必须至少有两个$1$和一个$0$。判断一下即可。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=505;
char s[N];
int T,n,m,num[N][2];
int main(){
    scanf("%d",&T);
    while(T--)
    {
        memset(num,0,sizeof(num));
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for (int j=1;j<=m;j++)
                num[j][s[j]-'0']++;
        }
        int k=0;
        for (int i=1;i<=m;i++)
        {
            int flag=0;
            if (num[i][0]<1) flag++;
            if (num[i][1]<2) flag+=2-num[i][1];
            k=max(flag,k);
        }
        printf("%d\n",k);
    }
    return 0;
}

T2 终焉之数列

题目大意:给定一个长度为$n$的数列$a_i$,现要求确定一个长度相等的序列$b_i$,使得$b$中任意两个数互质且最小化$\sum\limits_{i=1}^n |a_i-b_i|$。$n\leq 100,a_i\leq 30$。

发现$1-58$内只有$16$个质数,可以考虑状压(选$59$和选$1$是等价的)。

设$f_{i,s}$表示前$i$个数质因数状态为$s$的方案数。有转移:

$f_{i+1,s'}=f_{i,s}+|num-a_i|$

其中,$s'$为后继状态,$num$为一个合法的数。对于每个$s$合法的$num$可以预处理得到,对于$s$和$num$的$s'$也可以预处理得到。题目要求输出方案,记录一下前驱即可。时间复杂度$O(2^{16}\times 58\times n)$。

代码:

#include<cstdio>
#include<iostream>
#include<stack>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
const int N=105;
const int M=65536;
int prime[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
int f[N][M+5],g[N][M+5],t[N][M+5],s[N][M+5],a[N],n;
vector<int> v[M+5];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f; 
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for(int i=0;i<(1<<16);i++){
        for(int j=1;j<=58;j++){
            int flag=0;
            for(int k=1;k<=16;k++){
                if((j%prime[k]==0)&&(i&(1<<(k-1)))){
                    flag=1;
                    break;
                }
            }
            if(flag==0){
                v[i].push_back(j);
                int ss=i;
                for(int k=1;k<=16;k++){
                    if((j%prime[k]==0)&&((i&(1<<(k-1)))==0)){
                        ss|=(1<<(k-1));
                    }
                }
                s[j][i]=ss;
            }
        }
    }
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int i=0;i<(1<<16);i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<v[i].size();k++){
                if(f[j+1][s[v[i][k]][i]]>f[j][i]+abs(v[i][k]-a[j+1])){
                    f[j+1][s[v[i][k]][i]]=f[j][i]+abs(v[i][k]-a[j+1]);
                    g[j+1][s[v[i][k]][i]]=v[i][k];
                    t[j+1][s[v[i][k]][i]]=i;
                }
            }
        }
    }
    int pos,minn=0x3f3f3f3f;
    for(int i=0;i<(1<<16);i++){
        if(f[n][i]<minn){
            pos=i;
            minn=f[n][i];
        }
    }
    stack<int> s;
    for(int i=n;i>=1;i--){
        s.push(g[i][pos]);
        pos=t[i][pos];
    }
    while(!s.empty()){
        int x=s.top();
        s.pop();
        printf("%d ",x);
    }
    return 0;
}

T3 下棋

题目大意:给定$n$个大小为$1\times l_i$的棋盘,两个人轮流在上面下棋。规定落子的地方不能有棋子,且不能与其它棋子相邻。问是否先手必胜。

傻逼题。对$sg$函数打表发现循环节为$34$,直接判一下即可……

代码:

#include<bits/stdc++.h>
#define reg register
#define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
char B[1<<15],*S=B,*T=B;
int read()
{
    reg int s=0,f=1; reg char ch;
    for(;(ch=getchar())<'0'||ch>'9';ch=='-'?f=-f:0);
    for(;ch>='0'&&ch<='9';s=s*10+ch-'0',ch=getchar());
    return s*f;
}
int sg[110]={0,1},vis[110];
int SG(reg int x) {return x<=51?sg[x]:sg[51+(x-51)%34+(!((x-51)%34)?34:0)];}
int main()
{
    for(reg int i=2,k;i<=85;++i)
    {
        vis[sg[i-2]]=i;
        for(reg int j=0;j<=i-3;++j)
            vis[sg[j]^sg[i-3-j]]=i;
        for(k=0;vis[k]==i;++k);
        sg[i]=k;
    }
    for(reg int t=read();t--;)
    {
        reg int ans=0;
        for(reg int n=read();n--;ans^=SG(read()));
        puts(ans?"Alice":"Bob");
    }
    return 0;
}

T4 魔方

题目大意:给定一个三阶魔方,每个格子上有一个数字。给定其平面展开图。对于三阶魔方有$18$种旋转操作。问经过若干次旋转之后的展开图。

这题太TM傻逼了。没有任何技术含量,就纯粹模拟。让我当了一会码农……

如果旋转的不是中间的部分也会带着旁边的一面旋转……还有注意格子与格子的对应关系(说多了都是泪QAQ)。

没什么多说的,直接上代码……

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int a[7][5][5],tmp[7][5][5];
char s[10005];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//1:3->1->6->5->3
inline void r1(int j)
{
    for (int i=1;i<=3;i++)
    {
        a[1][i][j]=tmp[6][i][j];
        a[3][i][j]=tmp[1][i][j];
        a[5][i][j]=tmp[3][i][j];
        a[6][i][j]=tmp[5][i][j];
    }
    if (j==2) return;
    if (j==1)
    {
        a[2][1][3]=tmp[2][1][1];a[2][2][3]=tmp[2][1][2];a[2][3][3]=tmp[2][1][3];
        a[2][1][2]=tmp[2][2][1];a[2][2][2]=tmp[2][2][2];a[2][3][2]=tmp[2][2][3];
        a[2][1][1]=tmp[2][3][1];a[2][2][1]=tmp[2][3][2];a[2][3][1]=tmp[2][3][3];
    }
    else
    {
        a[4][3][1]=tmp[4][1][1];a[4][2][1]=tmp[4][1][2];a[4][1][1]=tmp[4][1][3];
        a[4][3][2]=tmp[4][2][1];a[4][2][2]=tmp[4][2][2];a[4][1][2]=tmp[4][2][3];
        a[4][3][3]=tmp[4][3][1];a[4][2][3]=tmp[4][3][2];a[4][1][3]=tmp[4][3][3];
    }
}
inline void f1(int j)
{
    for (int i=1;i<=3;i++)
    {
        a[5][i][j]=tmp[6][i][j];
        a[3][i][j]=tmp[5][i][j];
        a[1][i][j]=tmp[3][i][j];
        a[6][i][j]=tmp[1][i][j];
    }
    if (j==2) return;
    if (j==1)
    {
        a[2][1][1]=tmp[2][1][3];a[2][1][2]=tmp[2][2][3];a[2][1][3]=tmp[2][3][3];
        a[2][2][1]=tmp[2][1][2];a[2][2][2]=tmp[2][2][2];a[2][2][3]=tmp[2][3][2];
        a[2][3][1]=tmp[2][1][1];a[2][3][2]=tmp[2][2][1];a[2][3][3]=tmp[2][3][1];    
    }
    else
    {
        a[4][1][1]=tmp[4][3][1];a[4][1][2]=tmp[4][2][1];a[4][1][3]=tmp[4][1][1];
        a[4][2][1]=tmp[4][3][2];a[4][2][2]=tmp[4][2][2];a[4][2][3]=tmp[4][1][2];
        a[4][3][1]=tmp[4][3][3];a[4][3][2]=tmp[4][2][3];a[4][3][3]=tmp[4][1][3];
    }
}
inline void r2(int j)
{
    if (j==1)
    {
        a[4][1][1]=tmp[1][3][1];a[4][2][1]=tmp[1][3][2];a[4][3][1]=tmp[1][3][3];
        a[1][3][3]=tmp[2][1][3];a[1][3][2]=tmp[2][2][3];a[1][3][1]=tmp[2][3][3];
        a[2][1][3]=tmp[5][1][1];a[2][2][3]=tmp[5][1][2];a[2][3][3]=tmp[5][1][3];
        a[5][1][3]=tmp[4][1][1];a[5][1][2]=tmp[4][2][1];a[5][1][1]=tmp[4][3][1];
    }
    if (j==2)
    {
        a[4][1][2]=tmp[1][2][1];a[4][2][2]=tmp[1][2][2];a[4][3][2]=tmp[1][2][3];
        a[1][2][3]=tmp[2][1][2];a[1][2][2]=tmp[2][2][2];a[1][2][1]=tmp[2][3][2];
        a[2][1][2]=tmp[5][2][1];a[2][2][2]=tmp[5][2][2];a[2][3][2]=tmp[5][2][3];
        a[5][2][3]=tmp[4][1][2];a[5][2][2]=tmp[4][2][2];a[5][2][1]=tmp[4][3][2];
    }
    if (j==3)
    {
        a[4][1][3]=tmp[1][1][1];a[4][2][3]=tmp[1][1][2];a[4][3][3]=tmp[1][1][3];
        a[1][1][3]=tmp[2][1][1];a[1][1][2]=tmp[2][2][1];a[1][1][1]=tmp[2][3][1];
        a[2][1][1]=tmp[5][3][1];a[2][2][1]=tmp[5][3][2];a[2][3][1]=tmp[5][3][3];
        a[5][3][3]=tmp[4][1][3];a[5][3][2]=tmp[4][2][3];a[5][3][1]=tmp[4][3][3];
    }
    if (j==2) return;
    if (j==1)
    {
        a[3][1][3]=tmp[3][1][1];a[3][2][3]=tmp[3][1][2];a[3][3][3]=tmp[3][1][3];
        a[3][1][2]=tmp[3][2][1];a[3][2][2]=tmp[3][2][2];a[3][3][2]=tmp[3][2][3];
        a[3][1][1]=tmp[3][3][1];a[3][2][1]=tmp[3][3][2];a[3][3][1]=tmp[3][3][3];
    }
    if (j==3)
    {
        a[6][3][1]=tmp[6][1][1];a[6][2][1]=tmp[6][1][2];a[6][1][1]=tmp[6][1][3];
        a[6][3][2]=tmp[6][2][1];a[6][2][2]=tmp[6][2][2];a[6][1][2]=tmp[6][2][3];
        a[6][3][3]=tmp[6][3][1];a[6][2][3]=tmp[6][3][2];a[6][1][3]=tmp[6][3][3];
    }
}
//2:4->1->2->5->4
inline void f2(int j)
{
    if (j==1)
    {
        a[1][3][1]=tmp[4][1][1];a[1][3][2]=tmp[4][2][1];a[1][3][3]=tmp[4][3][1];
        a[2][1][3]=tmp[1][3][3];a[2][2][3]=tmp[1][3][2];a[2][3][3]=tmp[1][3][1];
        a[5][1][1]=tmp[2][1][3];a[5][1][2]=tmp[2][2][3];a[5][1][3]=tmp[2][3][3];
        a[4][1][1]=tmp[5][1][3];a[4][2][1]=tmp[5][1][2];a[4][3][1]=tmp[5][1][1];
    }
    if (j==2)
    {
        a[1][2][1]=tmp[4][1][2];a[1][2][2]=tmp[4][2][2];a[1][2][3]=tmp[4][3][2];
        a[2][1][2]=tmp[1][2][3];a[2][2][2]=tmp[1][2][2];a[2][3][2]=tmp[1][2][1];
        a[5][2][1]=tmp[2][1][2];a[5][2][2]=tmp[2][2][2];a[5][2][3]=tmp[2][3][2];
        a[4][1][2]=tmp[5][2][3];a[4][2][2]=tmp[5][2][2];a[4][3][2]=tmp[5][2][1];
    }
    if (j==3)
    {
        a[1][1][1]=tmp[4][1][3];a[1][1][2]=tmp[4][2][3];a[1][1][3]=tmp[4][3][3];
        a[2][1][1]=tmp[1][1][3];a[2][2][1]=tmp[1][1][2];a[2][3][1]=tmp[1][1][1];
        a[5][3][1]=tmp[2][1][1];a[5][3][2]=tmp[2][2][1];a[5][3][3]=tmp[2][3][1];
        a[4][1][3]=tmp[5][3][3];a[4][2][3]=tmp[5][3][2];a[4][3][3]=tmp[5][3][1];
    }
    if (j==2) return;
    if (j==1)
    {
        a[3][1][1]=tmp[3][1][3];a[3][1][2]=tmp[3][2][3];a[3][1][3]=tmp[3][3][3];
        a[3][2][1]=tmp[3][1][2];a[3][2][2]=tmp[3][2][2];a[3][2][3]=tmp[3][3][2];
        a[3][3][1]=tmp[3][1][1];a[3][3][2]=tmp[3][2][1];a[3][3][3]=tmp[3][3][1];
    }
    if (j==3)
    {
        a[6][1][1]=tmp[6][3][1];a[6][1][2]=tmp[6][2][1];a[6][1][3]=tmp[6][1][1];
        a[6][2][1]=tmp[6][3][2];a[6][2][2]=tmp[6][2][2];a[6][2][3]=tmp[6][1][2];
        a[6][3][1]=tmp[6][3][3];a[6][3][2]=tmp[6][2][3];a[6][3][3]=tmp[6][1][3];
    }
}
//3:3->4->6->2->3
inline void f3(int i)
{
    for (int j=1;j<=3;j++)
    {
        a[4][i][j]=tmp[3][i][j];
        a[6][3-i+1][3-j+1]=tmp[4][i][j];
        a[2][i][j]=tmp[6][3-i+1][3-j+1];
        a[3][i][j]=tmp[2][i][j];
    }
    if (i==2) return;
    if (i==1)
    {
        a[1][1][1]=tmp[1][1][3];a[1][1][2]=tmp[1][2][3];a[1][1][3]=tmp[1][3][3];
        a[1][2][1]=tmp[1][1][2];a[1][2][2]=tmp[1][2][2];a[1][2][3]=tmp[1][3][2];
        a[1][3][1]=tmp[1][1][1];a[1][3][2]=tmp[1][2][1];a[1][3][3]=tmp[1][3][1];
    }
    else
    {
        a[5][1][1]=tmp[5][3][1];a[5][1][2]=tmp[5][2][1];a[5][1][3]=tmp[5][1][1];
        a[5][2][1]=tmp[5][3][2];a[5][2][2]=tmp[5][2][2];a[5][2][3]=tmp[5][1][2];
        a[5][3][1]=tmp[5][3][3];a[5][3][2]=tmp[5][2][3];a[5][3][3]=tmp[5][1][3];
    }
}
inline void r3(int i)
{
    for (int j=1;j<=3;j++)
    {
        a[3][i][j]=tmp[4][i][j];
        a[4][i][j]=tmp[6][3-i+1][3-j+1];
        a[6][3-i+1][3-j+1]=tmp[2][i][j];
        a[2][i][j]=tmp[3][i][j];
    }
    if (i==2) return;
    if (i==1)
    {
        a[1][1][3]=tmp[1][1][1];a[1][2][3]=tmp[1][1][2];a[1][3][3]=tmp[1][1][3];
        a[1][1][2]=tmp[1][2][1];a[1][2][2]=tmp[1][2][2];a[1][3][2]=tmp[1][2][3];
        a[1][1][1]=tmp[1][3][1];a[1][2][1]=tmp[1][3][2];a[1][3][1]=tmp[1][3][3];
    }
    if (i==3)
    {
        a[5][3][1]=tmp[5][1][1];a[5][2][1]=tmp[5][1][2];a[5][1][1]=tmp[5][1][3];
        a[5][3][2]=tmp[5][2][1];a[5][2][2]=tmp[5][2][2];a[5][1][2]=tmp[5][2][3];
        a[5][3][3]=tmp[5][3][1];a[5][2][3]=tmp[5][3][2];a[5][1][3]=tmp[5][3][3];
    }
}
inline void output()
{
    for (int i=1;i<=3;i++)
        printf("%d %d %d \n",a[1][i][1],a[1][i][2],a[1][i][3]);
    for (int i=1;i<=3;i++)
    {
        printf("%d %d %d ",a[2][i][1],a[2][i][2],a[2][i][3]);
        printf("%d %d %d ",a[3][i][1],a[3][i][2],a[3][i][3]);
        printf("%d %d %d \n",a[4][i][1],a[4][i][2],a[4][i][3]);
    }
    for (int i=1;i<=3;i++)
        printf("%d %d %d \n",a[5][i][1],a[5][i][2],a[5][i][3]);
    for (int i=1;i<=3;i++)
        printf("%d %d %d \n",a[6][i][1],a[6][i][2],a[6][i][3]);
}
int main()
{
    for (int i=1;i<=3;i++)
        for (int j=1;j<=3;j++) a[1][i][j]=read();
    for (int i=1;i<=3;i++)
        for (int j=1;j<=9;j++)
        {
            if (j<=3) a[2][i][j]=read();
            if (j>3&&j<=6) a[3][i][j-3]=read();
            if (j>6&&j<=9) a[4][i][j-6]=read();
        }
    for (int i=1;i<=6;i++)
        for (int j=1;j<=3;j++)
        {
            if (i<=3) a[5][i][j]=read();
            else a[6][i-3][j]=read();
        }
    memcpy(tmp,a,sizeof(tmp));
    scanf("%s",s+1);
    int len=strlen(s+1);
    for (int i=1;i<=len;i++)
    {
        if (s[i]=='a'||s[i]=='b'||s[i]=='c') f1(s[i]-'a'+1);
        if (s[i]=='A'||s[i]=='B'||s[i]=='C') r1(s[i]-'A'+1);
        if (s[i]=='d'||s[i]=='e'||s[i]=='f') f2(s[i]-'d'+1);
        if (s[i]=='D'||s[i]=='E'||s[i]=='F') r2(s[i]-'D'+1);
        if (s[i]=='h'||s[i]=='i'||s[i]=='j') f3(s[i]-'h'+1);
        if (s[i]=='H'||s[i]=='I'||s[i]=='J') r3(s[i]-'H'+1);
        memcpy(tmp,a,sizeof(tmp));
    }
    output();
    return 0;
}

 

posted @ 2020-10-18 22:18  我亦如此向往  阅读(151)  评论(0编辑  收藏  举报