【NOIP模拟赛】【乱搞AC】【奇技淫巧】【乘法原理】回文串计数

回文串计数

(calc.pas/calc.c/calc.cpp)

【题目描述】

虽然是一名理科生,Mcx常常声称自己是一名真正的文科生。不知为何,他对于背诵总有一种莫名的热爱,这也促使他走向了以记忆量大而闻名的生物竞赛。然而,他很快发现这并不能满足他热爱背诵的心,但是作为一名强大的Boer,他找到了这么一条自虐的方式——背诵基因序列。不过这实在是太虐心了,就连Mcx也有些招架不住。不过他发现,如果他能事先知道这个序列里有多少对互不相交的回文串,他或许可以找到记忆的妙法。为了进一步验证这个方法,Mcx决定选取一个由小写字母构成的字符串SS来实验。不过由于互不相交的回文串实在过多,他很快就数晕了。不过他相信,在你的面前这个问题不过是小菜一碟。

【名词解释】

1.对于字符串SS,设其长度为Len,那么下文用Si表示SS中第i个字符(1<=i<=Len)

2.s[i,j]表示SS的一个字串,s[i,j] = “SiSi+1Si+2…Sj-2Sj-1Sj”,比如当SS为”abcgfd”时,

s[2,5] = “bcgf” , s[1,5] = “abcgf”

3.当一个串被称为一个回文串当且仅当将这个串反写后与原串相同,如”abcba”

4.考虑一个四元组(l,r,L,R) , 当s[l,r]和s[L,R]均为回文串时,且满足1 <= l <=r< L <= R <= Len时,我们称s[l,r]和s[L,R]为一对互不相交的回文串。也即本题所求即为这种四元组的个数。两个四元组相同当且仅当对应的l,r,L,R都相同。

【题目输入】

仅一行,为字符串SS,保证全部由小写字母构成,由换行符标志结束。

【题目输出】

仅一行,为一个整数,表示互不相交的回文串的对数。

【样例输入】

aaa

【样例输出】

5

【样例解释】

SS = “aaa” , SS的任意一个字串均为回文串,其中总计有5对互不相交的回文串:

(1,1,2,2) , (1,1,2,3) , (1,1,3,3) , (1,2,3,3) , (2,2,3,3).  (这里使用名词解释中的四元组进行表示)

【数据范围】

50%的数据满足SS的长度不超过200

100%的数据满足SS的长度不超过2000

【Solution】

  先吐槽一下这题的数据,O(N3)的大暴力过了90%的点....当然下面讲的是AC做法。

  首先用区间DP求出ch[i]到ch[j]之间是不是回文串,转移方程为pldr[i][j]=pldr[i+1][j-1],注意特判i==j和j-i+1==2的情况。然后N2求出每个字符之前(包括他自己)共有多少个回文字符串,再用N2求出每个字符之后 以这个字符相邻(去重)的字符为起点的回文字符串数量。最后N求出每个点之前的数目乘上之后的数目(乘法原理)的总和,即为答案。

  AC代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 char ch[2010];
 6 bool pldr[2010][2010];
 7 int lenn;
 8 int bef[2010],aft[2010];
 9 long long ans;
10 int main(){
11     scanf("%s",ch+1); lenn=strlen(ch+1);
12     for(int i=1;i<=lenn;++i) pldr[i][i]=true;
13     for(int i=lenn;i>=1;--i)
14         for(int j=i;j<=lenn;++j)
15             if(j>i&&ch[i]==ch[j]){
16                 if(i==j) pldr[i][j]=true;
17                 else if(j-i+1==2)pldr[i][j]=true;
18                 else pldr[i][j]=pldr[i+1][j-1];
19             }
20     for(int i=1;i<=lenn;++i){
21         bef[i]=bef[i-1];
22         for(int j=1;j<=i;++j)
23             if(pldr[j][i]) ++bef[i];
24     }
25     for(int i=1;i<lenn;++i)
26         for(int j=i;j<=lenn;++j)
27             if(pldr[i+1][j]) ++aft[i];
28     for(int i=1;i<=lenn;++i) ans+=bef[i]*aft[i];
29     printf("%I64d",ans);
30     return 0;
31 }
时间: 2024-12-24 13:48:49

【NOIP模拟赛】【乱搞AC】【奇技淫巧】【乘法原理】回文串计数的相关文章

【简单思考】noip模拟赛 NTR酋长

NTR酋长 (ntr.pas/.c/.cpp) 黄巨大终于如愿以偿的进入了czy的后宫中……但是czy很生气……他要在黄巨大走到他面前的必经之路上放上几个NTR酋长来阻挡黄巨大. 众所周知,NTR酋长有一个技能是沟壑(F).它会在地图上产生一条长长的障碍物阻挡人前进.Czy打算在一个n*m的矩形(必经之路?)中放上NTR酋长.NTR酋长要一个一个放下去,而且每放一个都会向四角倾斜的方向放出无限长的沟壑,而已经被沟壑挡住的地方就不能再放NTR酋长了. 请注意:不会出现沟壑的路径挡住另一个沟壑的情况

【noip模拟赛】 射击

这题似乎是什么安阳一中的模拟题,不管了,反正是学长出的noip模拟赛里面的题目.... 射击(shoot.pas/.c/.cpp) 时间限制:1s,内存限制128MB 题目描述: 据史书记载,对越反击战时期,有位中国侦察兵,他的代号叫814.一天他执行狙击任务,他的任务地区是n座恰巧在一条直线上的山.这些山所在直线恰巧为东西走向,山从东到西依次编号为1~n.一天814隐藏在编号为k的山上,每座山上都有1个目标. 814也非常的厉害,任务结束时杀了很多人,可是史书中只记载了两点: 1:814一定攻

NOIP模拟赛

#1[Nescafé 31]杯NOIP模拟赛 t1 题意:n*m的棋盘上从(1,1)走到(n,m),只能向下或向右,一些格子有老鼠,每个老鼠互不相同,当处于与老鼠有重边的格子时,视为看见了这只老鼠,求到终点看到最少的不同老鼠数. 分析:DP 由于求得是看到的不同的老鼠数目,不能直接用过河卒做,因为同一个位置的老鼠可能会统计多次,我们还需要增加一维即方向. f[i,j,0]表示到从上面一个格子走到(i,j)时最少老鼠数,f[i,j,1]表示左边. f[i,j,0]:=min(f[i-1,j,0]+

NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的命令进行移动,命令包括‘E’.‘S’.‘W’.‘N’四种,分别对应东南西北.执行某个命令时,它会向对应方向移动一个单位.作为新型机器人,它可以执行命令串.对于输入的命令串,每一秒它会按命令行动一次.执行完命令串的最后一个命令后,会自动从头开始循环.在0时刻时机器人

2012-10-20 NOIP模拟赛

      2012-10-20 NOIP模拟赛 by coolyangzc 共3道题目,时间3小时 题目名 高级打字机 不等数列 经营与开发 源文件 type.cpp/c/pas num.cpp/c/pas exploit.cpp/c/pas 输入文件 type.in num.in exploit.in 输出文件 type.out num.out exploit.out 时间限制 1000MS 1000MS 1000MS 内存限制 256MB 256MB 256MB 测试点 5+(5) 10

2017 9 11 noip模拟赛T2

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205; int map[N][N]; int d[N],tag[N],book[N],f[N]; int n,m; void work(int x) { memset(d,63,sizeof(d)); memset(book,0,sizeof(book)); memset(f,0,sizeof(

【noip模拟赛4】Matrix67的派对 暴力dfs

[noip模拟赛4]Matrix67的派对 描述 Matrix67发现身高接近的人似乎更合得来.Matrix67举办的派对共有N(1<=N<=10)个人参加,Matrix67需要把他们安排在圆桌上.Matrix67的安排原则是,圆桌上任意两个相邻人的身高之差不能超过K.请告诉Matrix67他共有多少种安排方法. 输入 第一行输入两个用空格隔开的数N和K,其中1<=N<=10,1<=K<=1 000 000. 第二行到第N+1行每行输入一个人的身高值.所有人的身高都是不

【NOIP模拟赛】与非 乱搞

biubiu~~~ 正解是线段树维护真值表,但是我觉得对于这道题来说乱搞就够了....... 我们发现如果我们把每一个数都一开始取反就会发现对于最后结果来说 x=x^1,x nand x=x|x ,x nand x nand x=x|x^1|x,x nand x nand x nand x=x|x^1|x^1|x.....而且我们还发现|0是无效,而且|1之后如有操作择从0开始若无操作则为1,那么我们可以维护我们处理过的x在序列上的前缀和以及他们从一开始进行操作然后每一位都停止一次的前缀答案和,

【NOIP模拟赛】beautiful 乱搞(平衡树)+ST

biubiu~~~ 我用平衡树处理的这道题,然而这种方法还是要看评测姬..... 正解是乱搞....就是枚举每一位数作为中位数,比他小的看做-1比他大的看做1,那么我们从一开始就有了一个绵延的山,我们记录这个数之前出现过的距水平线高度差,如果我们在右边找到了这个同样的距离就意味着我们中间的操作为0那么在这两个相同水平面之前的距离就是他作为中位数的一个区间. 似乎这是一种中位数套路........ #include <cstdio> namespace Pre{ inline void read