20190805

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值