【loj6436】【pkusc2018】神仙的游戏
Solution
个人觉得是道很好的法法塔题qwq
一开始的时候想偏了想到了另一种法法塔处理字符串匹配之类的奇怪技巧(万径人踪灭qwq了解一下),然后非常天真的想把问号拿出来单独处理一波然后越走越远。。。
好吧正解其实是(感觉貌似还是想的有点绕?应该有更加简便的思维方式不过qwq不管了qwq)
因为有一个问号所以其实挺难直接得到哪些长度能够匹配,那不妨换个思路把所有肯定不能匹配的长度去掉那剩下的就是答案了
肯定不能匹配的长度显然就是\(0\)和\(1\)对上了,假设我们现在知道位置\(x\)有一个\(0\),位置\(y\)有一个\(1\),那么考虑当匹配长度\(k\)满足什么条件的时候这两个位置是对上的,那么满足这样条件的\(k\)显然就是可以去掉的了,那么可以得到(假设字符串从\(0\)开始,\(x<y\) ,记\(y-x=len\),字符串总长度为\(n\)):
\]
化一下就是
\]
除此之外,这个匹配的话其实就是\(kmp\)那一套的感觉,因此用类似\(kmp\)推\(next\)数组那样的想法(额其实也不是吧不知道怎么说就是各种推来推去有点像的感觉qwq)去推一下这个串会发现这样一个性质:记两个匹配串的开头位置的差为\(K\),如果存在一对下标差为\(len\)的\(01\),那么满足\(K|len\)的长度都是无法匹配的
具体一点就是这样
第一个蓝点和红点的下标差是\(2K\)但是会影响到开头位置差为\(K\)的匹配
所以得知了\(01\)对的下标差之后我们再枚举一下倍数筛一下就可以了
至于\(01\)对的下标差,我们把\(x-y\)转成\(x+(n-1-y)\),这样的话就可以用法法塔来做了(注意\(s\)是从\(0\)开始的),考虑这样两个函数
g(x)&=\sum [s[n-1-i]==0]x^i\\
f(x)&=\sum [s[i]==1]x^i\\
\end{aligned}
\]
我们把指数看成上面的\(x\)和\(n-1-y\)然后直接这两个多项式乘一下,结果为\(h(x)\)
那么对于\(h(x)\)中指数小于\(n\)的部分,表示的是\(x>y\)的情况(因为这部分的指数\(-(n-1)\)得到的是负数),取反一下就可以得到下标差了,大于等于\(n\)的部分直接减就好了
最后枚举倍数筛一波然后输出就好了,注意这里的是首位的下标差所以\(i\)对应的长度应该是\(n-i\)
代码大概长这个样子(然而貌似用fft会更快但我也不知道为啥就写了ntt不管了qwq)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int MAXN=5*(1e5)+10,MOD=998244353,G=3;
int ksm(int x,int y);
namespace NTT{/*{{{*/
int A[MAXN*4],B[MAXN*4],W[MAXN*4][2],rev[MAXN*4];
int invg,len,invlen;
void init(){
invg=ksm(G,MOD-2);
for (int i=0;i<=20;++i){
W[1<<i][0]=ksm(G,(MOD-1)/(1<<i));
W[1<<i][1]=ksm(invg,(MOD-1)/(1<<i));
}
}
void prework(int *a,int *b,int n,int m){
for (int i=0;i<len;++i) A[i]=B[i]=0;
int bit=0;
for (len=1;len<n+m;len<<=1,++bit);
rev[0]=0;
for (int i=1;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
for (int i=0;i<=n;++i) A[i]=a[i];
for (int i=0;i<=m;++i) B[i]=b[i];
invlen=ksm(len,MOD-2);
}
void ntt(int *a,int op){
int w,w_n,t,u;
for (int i=0;i<len;++i)
if (rev[i]>i) swap(a[i],a[rev[i]]);
for (int step=2;step<=len;step<<=1){
w_n=op==1?W[step][0]:W[step][1];
for (int st=0;st<len;st+=step){
w=1;
for (int i=0;i<(step>>1);++i){
t=1LL*a[st+i+(step>>1)]*w%MOD;
u=a[st+i];
a[st+i]=(1LL*u+t)%MOD;
a[st+i+(step>>1)]=(1LL*u-t+MOD)%MOD;
w=1LL*w*w_n%MOD;
}
}
}
if (op==1) return;
for (int i=0;i<len;++i) a[i]=1LL*a[i]*invlen%MOD;
}
void Ntt(int *a,int *b,int n,int m){
prework(a,b,n,m);
ntt(A,1);
ntt(B,1);
for (int i=0;i<len;++i) A[i]=1LL*A[i]*B[i]%MOD;
ntt(A,-1);
}
void debug(int *a,int n){
prework(a,a,n,n);
ntt(a,1);
ntt(a,-1);
}
}/*}}}*/
char s[MAXN];
int ori1[MAXN],ori0[MAXN],res[MAXN*2];
int out[MAXN];
ll ans;
int n,m,lens;
void prework();
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%s",s);
n=strlen(s);
NTT::init();
prework();
NTT::Ntt(ori1,ori0,n,n);
for (int i=0;i<=n*2;++i) res[i]=NTT::A[i];
for (int i=0;i<n;++i) out[n-1-i]|=res[i];
for (int i=n;i<2*n-1;++i) out[i-(n-1)]|=res[i];
for (int i=1;i<=n;++i)
for (int j=i;j<=n&&!out[i];j+=i)
if (out[j]) out[i]=1;
ans=0;
for (int i=1;i<=n;++i)
if (!out[n-i]) ans^=1LL*i*i;
printf("%lld\n",ans);
}
int ksm(int x,int y){
int ret=1,base=x;
for (;y;y>>=1,base=1LL*base*base%MOD)
if (y&1) ret=1LL*ret*base%MOD;
return ret;
}
void prework(){
for (int i=0;i<n;++i)
ori1[i]=s[i]=='1',ori0[i]=s[i]=='0';
reverse(ori0,ori0+n);
}
【loj6436】【pkusc2018】神仙的游戏的更多相关文章
- LOJ6436 [PKUSC2018] 神仙的游戏 【FFT】
题目分析: 题目要求前后缀相同,把串反过来之后是一个很明显的卷积的形式.这样我们可以完成初步判断(即可以知道哪些必然不行). 然后考虑一下虽然卷积结果成立,但是存在问号冲突的情况. 箭头之间应当不存在 ...
- [LOJ6436][PKUSC2018]神仙的游戏
loj description 给你一个只有01和?的字符串,问你是否存在一种把?改成01的方案使串存在一个长度为\(1-n\)的\(border\).\(n\le5\times10^5\) sol ...
- BZOJ5372: [Pkusc2018]神仙的游戏
BZOJ5372: [Pkusc2018]神仙的游戏 https://lydsy.com/JudgeOnline/problem.php?id=5372 分析: 如果\(len\)为\(border\ ...
- BZOJ5372: PKUSC2018神仙的游戏
传送门 Sol 自己还是太 \(naive\) 了,上来就构造多项式和通配符直接匹配,然后遇到 \(border\) 相交的时候就 \(gg\) 了 神仙的游戏蒟蒻还是玩不来 一个小小的性质: 存在长 ...
- bzoj 5372: [Pkusc2018]神仙的游戏
Description 小D和小H是两位神仙.他们经常在一起玩神仙才会玩的一些游戏,比如"口算一个4位数是不是完全平方数". 今天他们发现了一种新的游戏:首先称s长度为len的前缀 ...
- loj 6436 PKUSC2018 神仙的游戏
传送门 好妙蛙 即串\(s\)长度为\(n\)首先考虑如果一个长度为\(len\)的\(border\)存在,当且仅当对所有\(i\in[1,len],s[i]=s[n-len+i]\),也就是所有模 ...
- BZOJ5372 PKUSC2018神仙的游戏(NTT)
首先有一个想法,翻转串后直接卷积看有没有0匹配上1.但这是必要而不充分的因为在原串和翻转串中?不能同时取两个值. 先有一些结论: 如果s中长度为len的前缀是border,那么其存在|s|-len的循 ...
- [PKUSC2018]神仙的游戏(FFT)
给定一个01?串,对所有len询问是否存在一种填法使存在长度为len的border. 首先有个套路的性质:对于一个长度为len的border,这个字符串一定有长度为n-len的循环节(最后可以不完整) ...
- [PKUSC2018]神仙的游戏
题目 画一画就会发现一些奇诡的性质 首先如果\(len\)为一个\(\operatorname{border}\),那么必然对于\(\forall i\in [1,len]\),都会有\(s_i=s_ ...
- 【LOJ6436】【PKUSC2018】神仙的游戏(NTT)
[LOJ6436][PKUSC2018]神仙的游戏(NTT) 题面 LOJ 题解 看到\(zsy\)从\(PKUSC\)回来就秒掉了这种神仙题 吓得我也赶快看了看\(PKUSC\)都有些什么神仙题 然 ...
随机推荐
- 关于scrum敏捷测试
关于scrum的一些定义 敏捷软件开发方法是一种把新增功能通过较小的循环逐步迭代添加到项目中(的项目管理方法),工作是由自我组织的团队以高效合作的方式拥抱和适应变化来保证客户需求被真正满足的方式来完成 ...
- Google Chrome插件分享
前言 浏览器是大家日常使用最多的工具之一,对于程序员来说,Google Chrome浏览器当然是大家优选的最爱之一.面对Chrome丰富的插件真的是爱不释手,如何把自己的Chrome调教成自己心仪的样 ...
- Linux学习——echo和read命令用法
转载自http://www.runoob.com/linux/linux-comm-read.html http://www.178linux.com/76331 echo命令 本文列举了echo命令 ...
- 作业要求20181113-4 Beta阶段第1周/共2周 Scrum立会报告+燃尽图 03
作业要求:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2385 版本控制:[https://git.coding.net/lglr201 ...
- UI分析之石家庄铁道大学官网
点击进入石家庄铁道大学的官方网站,首先映入眼帘的是“石家庄铁道大学”七个大字,配以蓝色背景和学校的俯瞰图,给人一种严谨又不失清新的感觉. 学校的网站首页界面主要有九个界面,分别是网站首页,学校概况,组 ...
- “我爱淘”第二冲刺阶段Scrum站立会议7
完成任务: 完成学院分类的点击查看书籍功能,可以点击书的条目查看书的详细信息.将登陆界面以及注册发布界面完善了一下修复一些bug. 计划任务: 将书的详细信息进行完善,并且可以点击收藏以及已预订等功能 ...
- Windows 10 系统下Python环境的搭建与配置
1. 在https://www.python.org/downloads/release/python-352/网站上下载python版本 2. 配置环境 右击计算机属性,然后选择高级系统设置 3. ...
- Python if后直接跟数字或字符串
(1)如果if后面的条件是数字,只要这个数字不是0,python都会把它当做True处理,见下面的例子 if 15: print 'YES' 输出YES,但是如果数字是0,就会被认为是False. ( ...
- 作业三C++
作业心得 1.本次作业开始使用C++编写了(面向过程的C++,2333) 2.粗略学习了一下文件输入输出,和项目的创建等(在大佬眼里最基本的操作QAQ,然而我还是有点晕晕的,平时都是ctrl+n新建源 ...
- PAT 甲级 1054 The Dominant Color
https://pintia.cn/problem-sets/994805342720868352/problems/994805422639136768 Behind the scenes in t ...