Atcoder Regular Contst 084 D - XorShift(bitset)
没错,这就是 Small Multiple 那场的 F,显然这种思维题对我来说都是不可做题/cg/cg/cg
首先如果我们把每个二进制数看作一个模 \(2\) 意义下的多项式 \(F(x)=\sum\limits_{i=0}^na_ix^i(a_i\in\{0,1\})\),那么上述操作就可以看作给一个多项式乘 \(x\) 和两个多项式加(减),我们记 \(D\) 为所有多项式的 \(\gcd\),或者更严谨一点,对于两个多项式 \(P(x),Q(x)\),我们定义 \(\gcd(P,Q)\) 为:
- 如果 \(Q=0\),那么 \(\gcd(P,Q)=P\)
- 否则不妨假设 \(\deg P\ge\deg Q\),那么 \(\gcd(P,Q)=\gcd(Q,P-Q\times x^{\deg P-\deg Q})\)
通过上面辗转相除的过程我们就能够从两个多项式 \(P,Q\) 得到它们的 \(\gcd(P,Q)\)。而显然对于一个多项式 \(F\),它的任意倍都是可以被表示出来的,具体来说就是不断给它乘 \(x\),然后把你要乘的那个倍数中为 \(1\) 的位加在一起。又因为任意时刻黑板上所有多项式都是 \(D\) 的倍数,因此我们可以得到结论:
Observation \(1\). 有且只有 \(D\) 的倍数能够被表示出来
也就是说我们的问题转化为要求有多少个多项式 \(P\) 满足:
- \(P\) 是 \(D\) 的倍数,也就是说 \(\exists Q,s.t. DQ=P\)
- \(P\) 在二进制表示下 \(\le X\)
考虑怎么求这个东西,我们按照字典序的套路枚举一个 \(l\) 满足 \(P\) 与 \(X\) 最高位到第 \(l+1\) 低的位均相同,且 \(P\) 第 \(l\) 低的位严格小于 \(X\) 第 \(l\) 低的位,但是这个东西还是一脸不好求的样子。不过别急,我们不妨再来找些性质:
Observation \(2\). 对于一个二进制数 \(T\),如果 \(T\) 从第 \(\deg D\) 到其最高位都已确定,那么存在唯一的确定后 \(\deg D\) 位的方式使其成为 \(D\) 的倍数
具体方法就是设将 \(T\) 后 \(\deg D\) 位全填上 \(0\) 得到的二进制数为 \(T_0\),那么我们就在 \(T\) 后 \(\deg D\) 位上填上 \(T_0\bmod D\),正确性显然。
有了这个性质之后此题就变得很可做了。如果 \(l\ge\deg D\),那么有 \(l-\deg D\) 位可以随便填,方案数为 \(2^{l-\deg D}\),否则 \(P\) 的 \(\deg D\) 位到最高位已经唯一确定了,因此我们就能唯一确定 \(P\) 的每一位取值,多项式取个模把它补全后与 \(X\) 比个大小即可。
时间复杂度 \(\mathcal O(n|a_i|^2)\),不过由于此题每一位取值只有 \(0/1\) 两种,因此我们可以很自然地想到 bitset 优化,这样取模和求 \(\text{gcd}\) 的复杂度均可降到 \(\mathcal O(\dfrac{|a_i|^2}{\omega})\),总复杂度就变成了 \(\mathcal O(\dfrac{n|a_i|^2}{\omega})\)
const int MAXN=4e3;
const int MOD=998244353;
struct poly{
bitset<MAXN+5> bs;int m;
void clear(){while(m&&!bs.test(m)) --m;}
};
poly getgcd(poly x,poly y){
while(x.bs.any()&&y.bs.any()){
if(x.m>=y.m) x.bs^=y.bs<<(x.m-y.m),x.clear();
else y.bs^=x.bs<<(y.m-x.m),y.clear();
} return (x.bs.any())?x:y;
}
poly getmod(poly x,poly y){
while(x.m>=y.m){
x.bs^=y.bs<<(x.m-y.m);
x.clear();
} return x;
}
poly d,tmp;int n,len,pw2[MAXN+5];
char m[MAXN+5],buf[MAXN+5];
int main(){
scanf("%d%s",&n,m+1);len=strlen(m+1);
for(int i=(pw2[0]=1);i<=len;i++) pw2[i]=pw2[i-1]*2%MOD;
for(int i=1;i<=n;i++){
scanf("%s",buf+1);int l=strlen(buf+1);tmp.bs.reset();tmp.m=l;
for(int j=1;j<=l;j++) if(buf[j]^48) tmp.bs.set(l-j+1);d=getgcd(d,tmp);
} if(len<d.m) return puts("1"),0;int ans=0;
for(int i=1;i<=len-d.m+1;i++) if(m[i]^48) ans=(ans+pw2[len-d.m+1-i])%MOD;
tmp.m=len;tmp.bs.reset();for(int i=1;i<=len-d.m+1;i++) if(m[i]^48) tmp.bs.set(len-i+1);
tmp=getmod(tmp,d);int add=1;
for(int i=d.m-1;i;i--){
if(tmp.bs.test(i)<(m[len-i+1]^48)){add=1;break;}
if(tmp.bs.test(i)>(m[len-i+1]^48)){add=0;break;}
} (ans+=add)%=MOD;printf("%d\n",ans);
return 0;
}
Atcoder Regular Contst 084 D - XorShift(bitset)的更多相关文章
- Atcoder Regular Contest 089 D - ColoringBalls(DP)
Atcoder 题面传送门 & 洛谷题面传送门 神仙题. 在下文中,方便起见,用 R/B 表示颜色序列中球的颜色,用 r/b 表示染色序列中将连续的区间染成的颜色. 首先碰到这一类计算有多少个 ...
- 【CF1097F】Alex and a TV Show(bitset)
[CF1097F]Alex and a TV Show(bitset) 题面 洛谷 CF 题解 首先模\(2\)意义下用\(bitset\)很明显了. 那么问题在于怎么处理那个\(gcd\)操作. 然 ...
- 3687: 简单题(bitset)
3687: 简单题 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 700 Solved: 319[Submit][Status][Discuss] ...
- [Bzoj5285][洛谷P4424][HNOI/AHOI2018]寻宝游戏(bitset)
P4424 [HNOI/AHOI2018]寻宝游戏 某大学每年都会有一次Mystery Hunt的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为新生 ...
- 【科技】位运算(bitset)优化最长公共子序列算法
最长公共子序列(LCS)问题 你有两个字符串 \(A,B\),字符集为 \(\Sigma\),求 \(A, B\) 的最长公共子序列. 简单动态规划 首先有一个广为人知的 dp:\(f_{i,j}\) ...
- Atcoder Regular Contest 125 E - Snack(最小割转化+贪心)
Preface: 这是生平第一道现场 AC 的 arc E,也生平第一次经历了 performance \(\ge 2800\),甚至还生平第一次被 hb 拉到会议里讲题,讲的就是这个题,然鹅比较尬 ...
- AtCoder Regular Contest 084 C - Snuke Festival【二分】
C - Snuke Festival ....最后想到了,可是不应该枚举a[],这样要二重循环,而应该枚举b[],这样只需一重循环... #include<iostream> #inclu ...
- Codeforces 333E Summer Earnings(bitset)
题目链接 Summer Earnings 类似MST_Kruskal的做法,连边后sort. 然后对于每条边,依次处理下来,当发现存在三角形时即停止.(具体细节见代码) 答案即为发现三角形时当前所在边 ...
- [Bzoj3687]简单题(bitset)
3687: 简单题 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1150 Solved: 565[Submit][Status][Discuss] ...
随机推荐
- Unity——EasyTouch摇杆插件使用
EasyTouch摇杆插件使用 Demo展示 双指缩放在电脑端无法掩饰,竖屏将就看看吧: 插件名叫EasyTouch,有需要给我留言,不想开仓库传了: 创建摇杆点这里: 初始化 On_Joystick ...
- Jupyter Notebook配置多个kernel
Jupyter Notebook配置多个kernel 前言: 在anaconda下配置了多个环境,而Jupiter Notebook只是安装在base环境下,为了能在Jupiter Notebook中 ...
- 零基础入门必备的Linux命令和C语言基础
文件和目录(底部有视频资料) cd /home 进入 '/ home' 目录' cd - 返回上一级目录 cd -/- 返回上两级目录 cd 进入个人的主目录 cd ~user1 进入个人的主目录 c ...
- 攻防世界 杂项14.Erik-Baleog-and-Olaf
下载解压后用notepad++打开 发现是一个PNG的图片文件,该后缀,再用Stegsolve打开看一下, 发现一个残缺二维码,果断在线PS补全 扫码得到flag flag{#justdiffit}
- 洛谷 P5658 [CSP-S2019] 括号树
链接: P5658 分析: 显然我们应该在dfs树的同时维护每个点的答案. 注意到第 \(u\) 个点的答案可以分成两部分,不包含 \(u\) 点时的答案,和加入 \(u\) 点后新增的答案,前者可以 ...
- linux 内核源代码情景分析——地址映射的全过程
linux 内核采用页式存储管理.虚拟地址空间划分成固定大小的"页面",由MMU在运行时将虚拟地址映射成某个物理内存页面中的地址.页式内存管理比段式内存管理有很多好处,但是由于In ...
- (1)Zookeeper在linux环境中搭建集群
1.简介 ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务.同步服务和命名注册.ZooKeeper的架构通过冗余服务实现高可用性.Zookeeper ...
- 『学了就忘』Linux基础命令 — 27、搜索操作相关命令
目录 1.whereis命令 2.which命令 3.locate命令 1.whereis命令 whereis是搜索系统命令的命令,也就是说,whereis命令不能搜索普通文件,而只能搜索系统命令. ...
- MySQL基础学习——SQL对数据库进行操作、对数据库的表进行操作
1.SQL对数据库进行操作: 创建数据库: 语法: create database 数据库名称 [character set 字符集 collate 字符集校对规则];字符集校对规则即所用字符集的数据 ...
- 前端调试工具(DevTools)
前端调试工具(DevTools) 开启:F12 布局 切换PC和移动端 页面元素的快速测试技巧 保持元素的hover等状态:选中当前行点击右键 元素状态改变的监控技巧 触发断点后元素状态不会再改变,可 ...