【题目链接】
【思路要点】
- 模 2 2 2 意义下,多项式平方相等于将每一项的指数翻倍。
- 我们需要维护一些关于字符串 S S S 的信息,使得其能够进行 “指数翻倍” 和 “指数翻倍并乘以原多项式” 的操作。
- 首先考虑测试点 6 , 7 , 8 6,7,8 6,7,8 。
- 考虑维护字符串 S S S 中 ∣ S ∣ − 17 |S|-17 ∣S∣−17 个长度为 18 18 18 的字符串中,每一种字符串的个数,以及 S S S 开头和结尾至多 50 50 50 个字符。
- “指数翻倍” 时,每一个长度为 18 18 18 的字符串将变为一个长度为 2 × 18 + 1 2\times18+1 2×18+1 的字符串,这里 + 1 +1 +1 是由于算上了两侧的 0 0 0 ,取最后两个长度为 18 18 18 的子串作为得到的新结果,并利用开头的若干字符更新边界上新产生的子串。
- “指数翻倍并乘以原多项式” 时,原多项式是一个次数最高为 18 18 18 的多项式,每一个长度为 18 18 18 的字符串 “指数翻倍” 后长度为 37 37 37 ,相乘后恰好最后两个长度为 18 18 18 的子串是准确的,而剩余长度为 18 18 18 的子串均包含了不能仅根据 “指数翻倍” 后的字符串计算的位置。依然取取最后两个长度为 18 18 18 的子串作为得到的新结果,并利用开头和结尾的若干字符更新边界上新产生的子串。
- 对于其余测试点,我们需要支持对前缀信息的询问,可以直接在每次倍增后删除掉字符串尾的若干字符做到,因此开头和结尾需要记录至少 2 N + c 2N+c 2N+c 个字符。
- 时间复杂度 O ( 2 max ( n , k ) × ( N + L o g M ) + N L o g M ) O(2^{\max(n,k)}\times (N+LogM)+NLogM) O(2max(n,k)×(N+LogM)+NLogM) 。
【代码】
#include<bits/stdc++.h> using namespace std; const int N = 17, M = 50, goal = (1 << 18) - 1; const int MAXN = 25, MAXLOG = 62; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(