Codeforces #299 Div 1 简要题解

来源:互联网 发布:阿里集团股份构成知乎 编辑:程序博客网 时间:2024/05/21 10:43

A. Tavas and Karafs(536A)

题目链接

http://codeforces.com/contest/536/problem/A

题目大意

给你一个首项为A,公差为B的等差序列(h1=A,hi=hi1+B)
n次询问(L,t,m),即在序列中找出一个最大的R,使得最多进行t次操作就能将hL...hR全部变为0,定义一次操作是在序列中选择不超过m个元素,并将它们全部减1

思路

首先给出一个引理:一个有限的等差序列P1....Pn,其中所有的元素均非负,若max{P1,P2...Pn}tiPimt,则我们称这个等差序列可以在t次操作内全部变为0,简称这个等差序列是完美的,该状态简写为一个二元组(m,t)

证明:
考虑两种情况。
1、该等差序列中非零数字个数不到m

我们可以每次操作把等差序列里所有的非零数字全部减1
由于iPimt,显然这个等差序列是完美的

2、该等差序列中非零数字个数大于等于m

我们首先找出这个序列里所有的Pi=t

满足上述条件的Pi显然不超过m个,因为若满足条件的Pi超过m个,那么就会使得最终的iPi>mt,与之前预设条件矛盾

然后将这些Pi全部减去1,假设共有x个符合条件的P(xm),那么此时在这个新序列里,max{P1,P2...Pn}t1iPi=iPixmtx,问题转换成(m,t1),如此反复,便会到情况1的状态,因此当前的序列也是完美的

代码

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>using namespace std;typedef long long int LL;LL A,B;int n;LL getKth(int x){    return A+(x-1)*B;}int main(){    scanf("%I64d%I64d%d",&A,&B,&n);    for(int i=1;i<=n;i++)    {        int L,t,m;        scanf("%d%d%d",&L,&t,&m);        LL fL=getKth(L);        int lowerBound=L,upperBound=1100000,ans=-1;        while(lowerBound<=upperBound)        {            int mid=(lowerBound+upperBound)>>1;            LL fM=getKth(mid);            LL sum=(fL+fM)*(mid-L+1)/2;            if(fM<=t&&sum<=(LL)m*t)            {                ans=mid;                lowerBound=mid+1;            }            else upperBound=mid-1;        }        printf("%d\n",ans);    }    return 0;}

B. Tavas and Malekas(536B)

题目链接

http://codeforces.com/contest/536/problem/B

题目大意

给你一个字符串P,要你构造一个长度为n的字符串S,使得以给定的m个下标作开头的后缀里,字符串P都是其中的前缀。

思路

显然要先把mP串插入到给定的m个位置上去,若mP串不相互冲突(在S串同样的位置上两个P串的字母都是相同的),假设插入了所有的字符串后,还有t个空位置,那么就能构造出26t个不同的长度为n的字符串。

那么如何判断mP串里是否存在某些对P串相互冲突呢?我们可以O(n)扫一遍每个P串,判断是否有与其相邻的P串,和它相交的那部分存在冲突,这个可以通过hash来判,为了防止被卡hash,建议使用双hash。

代码

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>#define MAXN 2100000#define MOD1 1000000007#define MOD2 1000000009#define BASE 233using namespace std;typedef long long int LL;int n,m;LL hash1[MAXN],pow1[MAXN]; //pow[i]=BASE^iLL hash2[MAXN],pow2[MAXN]; //pow[i]=BASE^ichar P[MAXN];LL gethash1(int L,int R){    return ((hash1[R]-hash1[L-1]*pow1[R-L+1]%MOD1)%MOD1+MOD1)%MOD1;}LL gethash2(int L,int R){    return ((hash2[R]-hash2[L-1]*pow2[R-L+1]%MOD2)%MOD2+MOD2)%MOD2;}bool mark[MAXN];int main(){    scanf("%d%d",&n,&m);    scanf("%s",P+1);    int len=strlen(P+1);    int freeNum=0;    pow1[0]=1;    for(int i=1;i<=n;i++) pow1[i]=pow1[i-1]*BASE%MOD1;    for(int i=1;i<=n;i++) hash1[i]=(hash1[i-1]*BASE%MOD1+P[i]-'a'+1)%MOD1;    pow2[0]=1;    for(int i=1;i<=n;i++) pow2[i]=pow2[i-1]*BASE%MOD2;    for(int i=1;i<=n;i++) hash2[i]=(hash2[i-1]*BASE%MOD2+P[i]-'a'+1)%MOD2;    int pre=0;    for(int i=1;i<=m;i++)    {        int x;        scanf("%d",&x);        mark[x]=true;    }    for(int i=1;i<=n;i++)    {        if(mark[i])        {            if(pre&&pre+len>i)            {                int tmp=pre+len-i;                if(gethash1(1,tmp)!=gethash1(len-tmp+1,len)||gethash2(1,tmp)!=gethash2(len-tmp+1,len))                {                    printf("0\n");                    return 0;                }            }            pre=i;        }        if(!pre||pre+len<=i) freeNum++;    }    LL ans=1;    for(int i=1;i<=freeNum;i++)        ans=(ans*26)%MOD1;    printf("%I64d\n",ans);    return 0;}
0 0
原创粉丝点击