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
*/