排列
题目描述
给定一个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;
}