11.21 考试

T1
给定一个字符串,有m次操作,可以使得相邻的字符交换,求最长相同的字符的长度最大的长度是多少;

考虑确定一个位置的字符不动为答案,那么其他与他相同的字符向他的方向交换;

设 f[i][j] 表示为 第i个字符不动,i字符后面的与i相同的字符转移j次,最多能使多少字符相邻;
g[i][j] 表示之前的;

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=60;
const int M=5010;
int n,m,ans;
char ch[N];
int f[N][M],g[N][M];
int main(){
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	scanf("%s",ch+1);
	n=strlen(ch+1);
	scanf("%d",&m);
	for(int i=1;i<=n;i++){
		char tt=ch[i];
		int t=0,sum=0,num=0;
		for(int j=i+1;j<=n;j++){
			if(ch[j]!=tt) t++;
			else{
				num++;
				sum+=t;
				f[i][sum]=num;
			}
		}
		t=0,sum=0,num=0;
		for(int j=i-1;j>=1;j--){
			if(ch[j]!=tt) t++;
			else{
				num++;
				sum+=t;
				g[i][sum]=num;
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			f[i][j]=max(f[i][j-1],f[i][j]);
			g[i][j]=max(g[i][j-1],g[i][j]);
		}
	}
//	for(int i=0;i<=m;i++) cout<<i<<" ";
//	cout<<"\n";
//	for(int i=1;i<=n;i++){
//		for(int j=0;j<=m;j++){
//			cout<<f[i][j]<<" ";
//		}
//		cout<<"\n";
//		for(int j=0;j<=m;j++){
//			cout<<g[i][j]<<" ";
//		}
//		cout<<"\n";
// 	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			ans=max(ans,f[i][j]+g[i][m-j]);
//			if(f[i][j]+g[i][m-j]==3){
//				cout<<i<<" "<<j<<"\n";
//			}
		}
	}
	cout<<ans+1;
	fclose(stdin);
	fclose(stdout);
	return 0;
}
/*
ABCCDCDDC
4

ABCCDCDDC
0

AABCCBCADEADDEADBFA
8

AABAAABABABABBABA
8
*/

T2
小林和亮亮在桃园里一起玩游戏。桃园里的桃树成行成列,刚好构成一个N×M的矩阵,亮亮在某
些桃树下放置了一些小礼物,要求小林把所有树下的礼物全部收集起来。小林从左上角的桃
树(1,1)出发,走到右下角的桃树(N,M)。他只能沿着路径向下或者向右走,某些桃树下有礼
物,他必须到达所有有礼物的树下并把礼物收集起来。小林在出发前,想请你帮他计算一
下,他有多少种不同的走法。由于答案可能很大,你只需要输出答案模100000000(10^8)后的值即可。

考虑把地图分成k段,因为要收到所有礼物,所以收到的顺序是确定的,不同的方案数就是当前礼物到下一个礼物所产生的方案;
可以证明(1,1,)到(n,m)只能向下或者向右走有多少种方案为C(n+m-2,m-1);
但是这题就麻烦在模数不是质数,所以要用到扩展卢卡斯定理;

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int N=1e4+7;
struct node{
	int x,y;
}e[N];
int n,m,k,ans=1,cnt;
int cmp(node x,node y){
	if(x.x==y.x) return x.y<y.y;
	return x.x<y.x;
}
int a[10010],c[10010];
int ksm(int a,int b,int p){
	int res=1;
	for(;b;b>>=1){
		if(b&1) res=1LL*res*a%p;
		a=1LL*a*a%p;
	}
	return res;
}
void exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;
		y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
int fac(int n,int p,int pk){
	if(!n) return 1;
	int res=1;
	for(int i=1;i<pk;i++){
		if(i%p) res=res*i%pk;
	}
	res=ksm(res,n/pk,pk);
	for(int i=1;i<=n%pk;i++){
		if(i%p) res=res*i%pk;
	}
	return res*fac(n/p,p,pk)%pk;
}
int inv(int a,int p){
	int x=0,y=0;
	exgcd(a,p,x,y);
	return (x%p+p)%p;
}
int C(int n,int m,int p,int pk){
	if(n<m) return 0;
	int f1,f2,f3;
	f1=fac(n,p,pk),f2=fac(m,p,pk),f3=fac(n-m,p,pk);
	int num=0;
	for(int i=n;i;i/=p) num+=i/p;
	for(int i=m;i;i/=p) num-=i/p;
	for(int i=n-m;i;i/=p) num-=i/p;
	return f1*inv(f2,pk)%pk*inv(f3,pk)%pk*ksm(p,num,pk)%pk;
}
int CRT(int cnt){
	int M=1,res=0;
	for(int i=1;i<=cnt;i++) M*=c[i];
	for(int i=1;i<=cnt;i++){
		int tt=M/c[i];
		res=(res+a[i]*tt%M*inv(tt,c[i])%M)%M;
	}
	return (res+M)%M;
}
int exlucas(int n,int m,int p){
	for(int i=2;i*i<=p;i++){
		int tt=1;
		while(p%i==0){
			tt*=i;
			p/=i;
		}
		if(tt>1){
			a[++cnt]=C(n,m,i,tt);
			c[cnt]=tt;
		}
	}
	if(p>1){
		a[++cnt]=C(n,m,p,p);
		c[cnt]=p;
	}
	return CRT(cnt);
}
main(){
	freopen("peach.in","r",stdin);
	freopen("peach.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=k;i++){
		scanf("%lld%lld",&e[i].x,&e[i].y);
	}
	sort(e+1,e+k+1,cmp);
	e[0].x=1;
	e[0].y=1;
	e[++k].x=n;
	e[k].y=m;
//	cout<<exlucas(5,2,100000000)<<"\n";
	for(int i=1;i<=k;i++){
		int tx=e[i].x-e[i-1].x+1;
		int ty=e[i].y-e[i-1].y+1;
		if(tx<=0||ty<=0){
			cout<<0;
			return 0;
		}
		cnt=0;
//		cout<<tx<<" "<<ty<<"\n";
//		cout<<exlucas(tx+ty-2,tx-1,100000000)<<"\n";
		ans=1LL*ans*exlucas(tx+ty-2,tx-1,100000000)%100000000;
	}
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
	return 0;
}
/*
5 4 1
2 2

5 4 2
2 2
2 3
*/
posted @ 2020-11-25 11:06  Aswert  阅读(90)  评论(0编辑  收藏  举报