2.14寒假模拟赛社论
T1
题意
略
思路
略
代码
略//只要会语言这题就不会错
T2
题意
心态爆炸的小S不想复习高代期中考了,他决定玩蛇。
小S先画了一个高度为n的三角形,从上往下第i层的宽度为i。
接下来,小S手上拿了一个字符串T,他会按蛇形从上往下循环地填这个字符串。
现在,在旁边看的小F有Q个问题。每个问题形如,在第ki行字符ci出现了多少次?
输入格式
第一行一个整数n。
第二行一个由大写字符构成的字符串,表示小S手上拿的字符串T。
第三行一个正整数Q。
接下来Q行,每行一个整数ki和一个大写字母ci。
输出格式
输出Q行,每行一个整数,表示答案。
100%的数据:1≤n≤10 18,1≤ki≤n,1≤Q≤50000,|T|≤10 6。
思路:
首先要知道蛇形和不蛇形在这题里没影响
然后我们开二维预处理出字符串某字符在某位值及其之前出现的次数(前缀和)
之后,每行可能有两大类情况:
1.这一行放不下到这一行末为止的字符数除以字符串长度的余数 -------余数-------(上行还有)
2.能放得下余数 上行余数过来的部分---| ----整串------ |-----整串----- |---余数
那么第一类我们就直接用余数减k,会得上一行末尾的最后一位在字符串中对应的位置,用余数前缀和减去上一行最后一位前缀和就可以了
第二类比较麻烦,先用 k减去余数就可以得到余数部分左边一位的位置,之后用这个东西除以字符串大小,得到整串数量,再用这个东西取模字符串大小,只要注意这里得的长度从后往前算就好了,(size前缀和)减去(用size减去取模后的长度的前缀和)得出左部分取余的前缀和
但这里注意一个点,就是数据实在是太大了,足足有10 18次方行,如果要对它及其之前的全部字符取模,要用(n*(n+1)/2)%size,运算量绝对爆long long
所以就利用公式(注意括号非常重要必须要加!)
(ab)%c=((a%c)(b%c))%c;
关于除以二的问题,你看n是奇是偶,如果是奇数就先除在n+1上,如果是偶数就先除在n上
代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
long long n;
string s1;
char s[5000000];
long long size;
long long q;
long long num[27][1000005];//在字符串上前缀和A的数量
//所有字母在使用时都减去64
inline char getch() {
char c=getchar();
while(c<'A'||c>'Z')c=getchar();
return c;
}
inline long long read() {
long long x=0,w=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-')w=-1;
c=getchar();
}
while(c<='9'&&c>='0') {
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
return x*w;
}
int main() {
n=read();
cin>>s1;
q=read();
size=s1.size();
for(int i=0; i<=size-1; i++)
s[i+1]=s1[i];
for(int i=1; i<=size; i++) {
num[s[i]-64][i]=num[s[i]-64][i-1]+1;
int d=s[i]-64;
for(int j=1; j<=26; j++) {
if(j!=d)
num[j][i]=num[j][i-1];
}
}
long long k;long long sum2;long long ans;long long sum1;long long e;
char c;long long yu1;long long l;long long r;long long q5;long long d;long long u;
for(int i=1; i<=q; i++) {
k=read();
c=getch();
ans=0;
if(k&1)
yu1=((k%size)*(((k+1)/2)%size))%size;
else
yu1=(((k/2)%size)*((k+1)%size))%size; //公式使用必须要严谨!该加括号的必须加括号!
l=0;
r=k;
if(yu1!=0) {
if(k>=yu1) {
ans=ans+num[c-64][yu1];
r=k-yu1;
} else {
ans=num[c-64][yu1]-num[c-64][yu1-k];
printf("%lld\n",ans);
continue;
}
}
if(r>l) { //说明都没到已经完全确定的时候
q5=((r-l)/size)*num[c-64][size];//算出所有最大值
e=(r-l)%size;
d=size-e;
u=num[c-64][size]-num[c-64][d];
ans+=q5;
ans+=u;
}
printf("%lld\n",ans);
}
return 0;
}