test 2017 9.18

排列

题目描述
给定一个n*n的矩阵f,你需要求出有多少个1~n的排列x满足对于1<=i≠j<=n,均有f[i,j]=min(x[i],x[j]),并输出字典序最小的一个。

有多组数据。

输入
第一行一个整数t表示数据组数。
每组数据第一行一个正整数n。接下来n行每行n个整数,第i行第j列的整数表示f[i,j]。

输出
对于每组数据,如果不存在这样的排列,输出一行一个整数-1。否则输出两行,第一行一个整数表示排列个数对998244353取模的结果,第二行n个整数表示字典序最小的排列。

样例输入
1
2
0 1
1 0
样例输出
2
1 2
提示
对于20%的数据,n<=8。
对于60%的数据,n<=40。
对于100%的数据,t<=10,∑n<=2000,f[i,i]=0,1<=fi,j<=n。
各档数据中均有一半保证全部有解。

Solution

可得答案只有-1或2,简单判断不合法情况。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int mod=998244353;
int cas,n,x;
ll ans;
int a[2005][2005];
int b[2005][2],c[2005],p[2005];
void prepare()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
    ans=1;
    for(int i=1;i<=n;i++) c[i]=b[i][0]=b[i][1]=p[i]=0;
}
void first()
{
    for(int i=1;i<=n;i++)
    for(int j=i+1;j<=n;j++)
    {
        if(a[i][j]!=a[j][i]) ans=-1;
        if(a[i][j]==n) ans=-1;
        x=a[i][j];
        if(c[x]==0) //此值还没出现过
        {
            b[x][0]=i;b[x][1]=j;c[x]=2;
        }
        else
        {
            if(c[x]==2) //第一次,要找公共部分
            {
                if(b[x][0]==i||b[x][1]==i)
                {
                    c[x]=1;b[x][0]=i;
                }
                else
                if(b[x][0]==j||b[x][1]==j)
                {
                    c[x]=1;b[x][0]=j;
                }
                else ans=-1;
            }
            else
            if(c[x]==1)
            {
                if(b[x][0]!=i&&b[x][0]!=j) ans=-1;
            }
        }
    }
}
void second()
{
    for(int i=1;i<n;i++)
    if(c[i]==1) //i值只对应一个下标
    {
        if(p[b[i][0]]==0) p[b[i][0]]=i; else ans=-1; //不合法
    }
    for(int i=1;i<n;i++)
    if(c[i]==2)
    {
        if(p[b[i][0]]==0&&p[b[i][1]]==0)
        {
            ans=ans*2;
            p[b[i][0]]=i;p[b[i][1]]=n;
        }
        else
        if(p[b[i][0]]>0&&p[b[i][1]]>0) ans=-1;
        else
        if(p[b[i][0]]==0) p[b[i][0]]=n;
        else
        if(p[b[i][1]]==0) p[b[i][1]]=n;
    }
}
int main()
{
    cin>>cas;
    while(cas--)
    {
        prepare();
        first();
        second();
        if(n==1)
        {
            if(a[1][1]==0)
            {
                cout<<"1"<<endl;
                cout<<"1 "<<endl;
            }
            else cout<<"-1"<<endl;
            continue;
        }
        if(ans<0) ans=-1;
        printf("%d\n",ans);
        if(ans>0)
        {
            for(int i=1;i<n;i++) printf("%d ",p[i]);
            printf("%d \n",p[n]);
        }
    }
    return 0;
}

字符串

题目描述
定义两个字符串A,B相似当且仅当满足以下两个条件中的至少一个:
(1)A和B相同;
(2)将A分为长度相同的两个子串A0,A1,将B分为长度相同的两个子串B0,B1,满足A0相似于B0,A1相似于B1或A0相似于B1,A1相似于B0。
给定两个字符串S,T,问它们是否相似。
有多组数据。

输入
第一行一个整数t表示数据组数。
每组数据第一行一个字符串S,第二行一个字符串T,保证它们长度相同。

输出
每组数据一行,若相似输出YES,不相似输出NO。

样例输入
2
abab
baab
aabb
abab
样例输出
YES
NO
提示
对于30%的数据,|S|<=30。
对于60%的数据,|S|<=100。
对于100%的数据,t<=30,∑|S|<=500000。

Solution

直接暴力递归

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
char a[500005],b[500005];
int n,cas;
int ty(int x1,int y1,int x2,int y2)
{
    int l=y1-x1+1,x=x1,y=x2,s=0;
    while(l--) 
    {
        if(a[x]==b[y]) s++;
        x++;
        y++;
    }
    if(s==y1-x1+1) return 1; //ПаµИ
    if((y1-x1+1)%2==1) return 0;
    int mid1=(x1+y1)/2,mid2=(x2+y2)/2;
    if(ty(x1,mid1,x2,mid2)==1&&ty(mid1+1,y1,mid2+1,y2)==1) return 1;
    if(ty(x1,mid1,mid2+1,y2)==1&&ty(mid1+1,y1,x2,mid2)==1) return 1;
    return 0;
}   
int main()
{
    cin>>cas;
    while(cas--) 
    {
        scanf("%s",a+1);
        scanf("%s",b+1);
        n=strlen(a+1);
        if(ty(1,n,1,n)==1) printf("YES\n"); else printf("NO\n");
    }
    return 0;
}
期望状态=未知(u)/安装(i)/删除(r)/清除(p)/保持(h) | 状态=未安装(n)/已安装(i)/仅存配置(c)/仅解压缩(U)/配置失败(F)/不完全安装(H)/触> |/ 错误?=(无)/须重装(R) (状态,错误:大写=故障) ||/ 名称 版本 体系结构 描述 +++-===============-================-============-=============================> ii build-essential 12.8ubuntu1.1 amd64 Informational list of build-e> ii gcc 4:9.3.0-1ubuntu2 amd64 GNU C compiler ii libc6-dev:amd64 2.31-0ubuntu9.18 amd64 GNU C Library: Development Li> ii make 4.2.1-1.2 amd64 utility for directing compila> --version...skipping... 期望状态=未知(u)/安装(i)/删除(r)/清除(p)/保持(h) | 状态=未安装(n)/已安装(i)/仅存配置(c)/仅解压缩(U)/配置失败(F)/不完全安装(H)/触> |/ 错误?=(无)/须重装(R) (状态,错误:大写=故障) ||/ 名称 版本 体系结构 描述 +++-===============-================-============-=============================> ii build-essential 12.8ubuntu1.1 amd64 Informational list of build-e> ii gcc 4:9.3.0-1ubuntu2 amd64 GNU C compiler ii libc6-dev:amd64 2.31-0ubuntu9.18 amd64 GNU C Library: Development Li> ii make 4.2.1-1.2 amd64 utility for directing compila> ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ set mark: ...skipping... 期望状态=未知(u)/安装(i)/删除(r)/清除(p)/保持(h) | 状态=未安装(n)/已安装(i)/仅存配置(c)/仅解压缩(U)/配置失败(F)/不完全安装(H)/触> |/ 错误?=(无)/须重装(R) (状态,错误:大写=故障) ||/ 名称 版本 体系结构 描述 +++-===============-================-============-=============================> ii build-essential 12.8ubuntu1.1 amd64 Informational list of build-e> ii gcc 4:9.3.0-1ubuntu2 amd64 GNU C compiler ii libc6-dev:amd64 2.31-0ubuntu9.18 amd64 GNU C Library: Development Li> ii make 4.2.1-1.2 amd64 utility for directing compila> ~
07-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值