【马三模拟赛】Day2题解
这套是黈力的题,题目应该比我出的难,每道题都想了好久,没有一眼秒,因为种种原因晚交了7min,如果多7min就能多30分啊。
T1 马三的数列
很明显只要对于每个数求出在左边最多能伸展几个,右边最多能伸展几个,乘起来就可以了
于是每次维护一个单调下降的数列,然后一个一个数加进来判断就行啦
一开始没考虑负数,幸亏黈力提醒,不然就爆0啦!
#include<cstdio>
#define N 1111111
long long n,i,j,u,now,head,a[N],ans1[N],ans2[N],q[N];char ch;
int main(){
scanf("%lld",&n);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
a[0]=-2e9;q[1]=1;head=1;ans1[1]=1;
for(i=2;i<=n;i++){
while(a[i]>a[q[head]]&&head)head--;
ans1[i]=i-q[head];
q[++head]=i;
}
a[n+1]=-2e9;q[0]=n+1;q[1]=n;head=1;ans2[n]=1;
for(i=n-1;i;i--){
while(a[i]>=a[q[head]]&&head)head--;
ans2[i]=q[head]-i;
q[++head]=i;
}
for(i=1;i<=n;i++)printf("%lld ",ans1[i]*ans2[i]);
}
T2 马三的宝箱
一开始就想到把一个A,一个B,一个C取出来,剩下的再排,但似乎没法做
然后考虑AB、AC、BC之间两两的关系,想把他们都符合条件的概率容斥一下算出来,但答案不对,因为两两之间的关系会互相影响,所以概率不能这么算
然后我把初始的全排列全写了出来,一开始写错了。。然后发现似乎一开始A和B的关系固定,然后把AB打包起来和C比就行了
于是先求出全排列方案数ans,然后维护一个前缀和sum[i],每次ans=ans*a[i]/sum[i],因为要让前面的打包起来合法,必须要让至少有一个i放到最后
然后求的时候可以用分子和分母先求好,求完后再逆元弄一次就可以了
#include<cstdio>
#define MOD 1000000007
#define N 222222
typedef long long LL;
LL n,i,j,fz,fm,x,y,a[N],sum[N];
void exgcd(LL a,LL b,LL &x,LL &y){
if(!b){x=1;y=0;return;}
exgcd(b,a%b,x,y);
LL t=x;x=y;y=t-a/b*y;
}
int main(){
scanf("%lld",&n);
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
fz=1;for(i=2;i<=sum[n];i++)fz=(fz*i)%MOD;
fm=1;for(i=1;i<=n;i++)for(j=2;j<=a[i];j++)fm=(fm*j)%MOD;
for(i=2;i<=n;i++){
fz=(fz*a[i])%MOD;
fm=(fm*sum[i])%MOD;
}
exgcd(fm,MOD,x,y);
if(x<0)x+=MOD;
printf("%lld",(fz*x)%MOD);
}
T3 马三的密码
用了个傻逼的算法:HASH+矩乘 过了6个点,但写了好久、、
#include<cstdio>
#include<cstring>
#define MOD 1000000007
long long n,p,q,x,i,j,now,wil,T,w,hash[1111111];bool ff;
char s[1111111],ss[1111111],ch;
struct JZ{long long x,y,m[3][3];}ans,def;
JZ cheng(JZ a,JZ b){
JZ c;memset(c.m,0,sizeof c.m);
c.x=a.x;c.y=b.y;
for(int i=1;i<=a.x;i++)
for(int j=1;j<=b.y;j++)
for(int k=1;k<=a.y;k++)
c.m[i][j]=(c.m[i][j]+(a.m[i][k]*b.m[k][j])%MOD)%MOD;
return c;
}
int main(){
scanf("%s",s);n=strlen(s);
if(n>1111){
scanf("%lld",&T);
hash[0]=s[0]-'a'+1;
for(i=1;i<n;i++)hash[i]=(hash[i-1]*27+s[i]-'a'+1)%MOD;
while(T--){
scanf("%lld",&p);
if(p==1){
scanf("%lld",&x);
scanf("%s",ss);
s[x-1]=ss[0];
}else if(p==2){
scanf("%s",ss);
hash[n]=(hash[n-1]*27+ss[0]-'a'+1)%MOD;
s[n]=ss[0];
n++;
}else if(p==3){
scanf("%s",ss);p=strlen(ss);
now=ss[0]-'a'+1;w=27;for(j=1;j<p;j++)now=(now*27+ss[j]-'a'+1)%MOD,w=(w*27)%MOD;
q=n/p;wil=hash[p*q-1];
ans.x=1;ans.y=2;
ans.m[1][1]=now;
ans.m[1][2]=1;
def.x=def.y=2;
def.m[1][1]=w;def.m[1][2]=0;
def.m[2][1]=now;def.m[2][2]=1;
w=q-1;
for(;w;w>>=1){
if(w&1)ans=cheng(ans,def);
def=cheng(def,def);
}
if(ans.m[1][1]==wil){
ff=1;
for(i=p*q;i<n;i++)if(ss[i-p*q]!=s[i]){ff=0;break;}
if(ff)puts("YES");else puts("NO");
}else puts("NO");
}
}
}else{
scanf("%d",&n);
while(n--){
scanf("%d",&p);
if(p==1){
scanf("%d",&x);
scanf("%s",ss);
s[x-1]=ss[0];
}else if(p==2){
scanf("%s",ss);
for(j=0;j<strlen(ss);j++)s[strlen(s)]=ss[j];
}else if(p==3){
scanf("%s",ss);now=strlen(ss);ff=1;
for(j=0;j<strlen(s);j++)
if(ss[j%now]!=s[j]){ff=0;break;}
if(ff)puts("YES");else puts("NO");
}
}
}
}
2015年7月14日 14:55
黈力的题多良心比你出的简单不知多少倍
2015年7月14日 14:56
只过了6个点就好意思说自己ak了
2015年7月15日 15:14
被主力爷骂了~~~~(>_<)~~~~