NOIP 模拟赛
一、题目概览
中文题目名称 排列 字符串 数
英文题目名称 permutation string number
可执行文件名 permutation string number
输入文件名 permutation.in string.in number.in
输出文件名 permutation.out string.out number.out
每个测试点时限 1s 1s 1s
测试点数目 10 10 10
每个测试点分值 10 10 10
比较方式 全文比较 全文比较 全文比较
题目类型 传统 传统 传统
运行内存上限 256MB 256MB 256MB
二、提交源程序文件名
对于 Pascal permutation.pas string.pas number.pas
对于 C 语言 permutation.c string.c number.c
对于 C++语言 permutation.cpp string.cpp number.cpp
三、注意事项:
1.文件名(程序名和输入输出文件名)必须使用小写。
2.C/C++中函数 main()的返回值类型必须是 int,程序正常结束时的返回值必须
是 0。
3.评测环境为 Windows,使用 lemon 进行评测,开启 O2 优化。
排列(permutation)
【题目描述】
给定一个 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<=f[i,j](i ≠ j)<=n。
各档数据中均有一半保证全部有解。
字符串(string)
【题目描述】
定义两个字符串 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。
数(number)
【题目描述】
给定正整数 n,m,问有多少个正整数满足:
(1)不含前导 0;
(2)是 m 的倍数;
(3)可以通过重排列各个数位得到 n。
【输入数据】
一行两个整数 n,m。
【输出数据】
一行一个整数表示答案对 998244353 取模的结果。
【样例输入】
1 1
【样例输出】
1
【数据范围】
对于 20%的数据,n<10^10。
对于 50%的数据,n<10^16,m<=20。
对于 100%的数据,n<10^20,m<=100。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int q=998244353;
int n,m,x[20],a[20],f[60000][110],g[60000],p[100];
char s[100];
inline void add(int &a,int b)
{
a=(a+b<q?(a+b):(a+b-q));
}
int main()
{
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
int i,j,k;
scanf("%s%d",&s,&m);
n=strlen(s);
for(i=0;i<n;i++)
x[s[i]-'0']++;
a[0]=1;
for(i=0;i<=9;i++)
a[i+1]=a[i]*(x[i]+1);
for(i=1;i<a[10];i++)
for(j=0;j<=9;j++)
if(i%a[j+1]/a[j])
g[i]=g[i-a[j]]+1;
p[0]=1;
for(i=1;i<n;i++)
p[i]=p[i-1]*10%m;
f[0][0]=1;
for(i=1;i<a[10];i++)
for(j=(i==a[10]-1);j<=9;j++)
if(i%a[j+1]/a[j])
for(k=0;k<m;k++)
add(f[i][k],f[i-a[j]][((k-p[g[i]-1]*j)%m+m)%m]);
printf("%d\n",f[a[10]-1][0]);
return 0;
}
//
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int t,n,x[2010][2010],f[2010],a[2010];
int main()
{
freopen("permutation.in","r",stdin);
freopen("permutation.out","w",stdout);
int i,j,k;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
k=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&x[i][j]);
if(x[i][j]==n-1)
k=i;
}
for(i=1;i<=n;i++)
f[i]=x[k][i];
f[k]=n;
for(i=1,k=0;i<=n;i++)
for(j=1;j<=n;j++)
if(j!=i && x[i][j]!=min(f[i],f[j]))
k=1;
for(i=1;i<=n;i++)
a[i]=0;
for(i=1;i<=n && !a[f[i]];i++)
a[f[i]]=1;
if(k || i<=n)
printf("-1\n");
else
{
printf("2\n");
for(i=1;i<=n;i++)
printf("%d ",f[i]);
printf("\n");
}
}
return 0;
}
//
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int T,n;
char s[500010],t[500010];
inline void orz(char s[],int l,int r)
{
if(r-l&1)
return;
int i,m=(l+r>>1);
orz(s,l,m);
orz(s,m,r);
for(i=0;i<m-l;i++)
if(s[l+i]!=s[m+i])
break;
if(i<m-l && s[l+i]>s[m+i])
for(i=0;i<m-l;i++)
swap(s[l+i],s[m+i]);
}
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
int i;
scanf("%d",&T);
while(T--)
{
scanf("%s%s",&s,&t);
n=strlen(s);
orz(s,0,n);
orz(t,0,n);
for(i=0;i<n;i++)
if(s[i]!=t[i])
break;
if(i<n)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}