A. Tavas and Karafs(536A)
题目链接
http://codeforces.com/contest/536/problem/A
题目大意
给你一个首项为
A
,公差为
n
次询问
思路
首先给出一个引理:一个有限的等差序列
证明:
考虑两种情况。
1、该等差序列中非零数字个数不到
m
个
我们可以每次操作把等差序列里所有的非零数字全部减1
由于∑iPi≤mt ,显然这个等差序列是完美的2、该等差序列中非零数字个数大于等于 m
我们首先找出这个序列里所有的
Pi=t 满足上述条件的 Pi 显然不超过 m 个,因为若满足条件的
Pi 超过 m 个,那么就会使得最终的∑iPi>mt ,与之前预设条件矛盾然后将这些 Pi 全部减去1,假设共有 x 个符合条件的
P(x≤m) ,那么此时在这个新序列里, max{P′1,P′2...P′n}≤t−1 , ∑iP′i=∑iPi−x≤mt−x ,问题转换成 (m,t−1) ,如此反复,便会到情况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 都是其中的前缀。思路
显然要先把
m 个 P 串插入到给定的m 个位置上去,若 m 个P 串不相互冲突(在 S 串同样的位置上两个P 串的字母都是相同的),假设插入了所有的字符串后,还有 t 个空位置,那么就能构造出26t 个不同的长度为 n 的字符串。那么如何判断
m 个 P 串里是否存在某些对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 233 using namespace std; typedef long long int LL; int n,m; LL hash1[MAXN],pow1[MAXN]; //pow[i]=BASE^i LL hash2[MAXN],pow2[MAXN]; //pow[i]=BASE^i char 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; }