luogu

bzoj

sol

枚举一个长度为\(n\)为回文串,它的所有循环位移都可以产生贡献。

但是这样算重了。重复的地方在于可能多个回文串循环同构,或者可能有的回文串经过小于\(n\)次循环位移后能够得到自身。

一个比较好的处理方式是:对每个回文串求最小的\(x\)使这个串经过\(x\)次循环位移后可以再次成为一个回文串。这样对每个回文串求\(\sum x\)显然就不会算重了。

考虑一个串的\(x\)是什么。显然会和这个串的最小循环节长度有关。实际上如果最小循环节长度为偶数,那么\(x\)就会是这个长度的一半;否则就等于这个长度。

形式化地,如果一个回文串的最小循环节长度为\(i\),那么它对答案的贡献就是\(h(i)=i\frac{1+[i\mbox{是奇数}]}{2}\)。

设最小循环节为\(i\)的回文串共有\(f(i)\)个,那么我们要求的答案就是

\[Ans=\sum_{d|n}f(d)h(d)
\]

又因为$$\sum_{d|n}f(d)=k^{\lceil\frac n2\rceil}=g(n)$$

所以$$f(n)=\sum_{d|n}g(d)\mu(\frac nd)$$

代入原式$$Ans=\sum_{d|n}\sum_{i|d}g(i)\mu(\frac di)h(d)\=\sum_{i|n}g(i)\sum_{d|\frac ni}\mu(d)h(id)$$

我们希望可以把\(h(id)\)中的\(i\)提出来,这样后半部分就是一个关于\(\frac ni\)的函数了。

因为\(h(x)\)不是\(x\)就是\(\frac x2\),我们发现\(h(id)\neq d\times h(i)\)当且仅当\(i\)是奇数且\(d\)是偶数,而\(d|\frac ni\)所以\(d\)是偶数就说明\(\frac ni\)也是偶数。那么我们现在假设\(i\)是奇数且\(\frac ni\)是偶数,考虑下面这个式子的取值。

\[\sum_{d|\frac ni}\mu(d)h(id)
\]

显然只有\(\mu(d)\)非零项有贡献,而\(\frac ni\)中含有\(2\)这个因子就使得所有\(\mu(d)\)非零项中含\(2\)与不含\(2\)的\(d\)可以一一对应。他们的\(h(id)\)的值是相同的,而\(\mu(d)\)的值恰好相反,所以这个式子的值一定为\(0\)。

话说回来。我们现在已经知道了\(h(id)\neq d\times h(i)\)的情况没有贡献,就可以放心大胆地用这一种变换了。

\[Ans=\sum_{i|n}g(i)\sum_{d|\frac ni}\mu(d)h(id)\\=\sum_{i|n}g(i)h(i)\sum_{d|\frac ni}d\mu(d)
\]

(在枚举\(i\)时需要跳过\(i\)是奇数而\(\frac ni\)是偶数的项)

考虑后面的东西是个啥。还是只有\(\mu(d)\)非零项有贡献,也就是说含有奇数个质因子的\(d\)会乘上\(-1\),含有偶数个质因子的\(d\)为乘上\(1\),所以这个值相当于是将\(\frac ni\)质因数分解为\(p_1^{a_1}p_2^{a_2}...p_k^{a_k}\)后,为\(\prod_{i=1}^k(1-p_i)\)。

所以到这里就比较简单了。先用\(Pollard-Rho\)算法将\(n\)分解,再dfs枚举\(n\)的每一个约数\(d\),在搜索的过程中自然可以求出那个\(\prod_{i=1}^k(1-p_i)\)。

code

#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
#define ll long long
ll mul(ll x,ll y,ll m){
x%=m;y%=m;
return (x*y-(ll)(((long double)x*y+0.5)/(long double)m)*m+m)%m;
}
ll fastpow(ll x,ll y,ll m){
ll res=1;
while (y) {if (y&1) res=mul(res,x,m);x=mul(x,x,m);y>>=1;}
return res;
}
ll f[]={2,3,5,7,11,13,17,19,23,29};
bool MR(ll p){
for (int i=0;i<10;++i){
if (p<=f[i]) break;
if (fastpow(f[i],p-1,p)!=1) return false;
ll pp=p-1;
while (~pp&1){
pp>>=1;ll y=fastpow(f[i],pp,p);
if (mul(y,y,p)==1&&y!=1&&y!=p-1) return false;
}
}
return true;
}
ll PR(ll n,ll c){
ll i=0,k=2,x,y;x=y=1+rand()%(n-1);
while (1){
x=(mul(x,x,n)+c)%n;
ll d=__gcd((y-x+n)%n,n);
if (d!=1&&d!=n) return d;
if (x==y) return n;
if (++i==k) y=x,k<<=1;
}
}
ll tmp[100];int len;
void fact(ll n){
if (n==1) return;
if (MR(n)) {tmp[++len]=n;return;}
ll p=n;for (int c=233;p==n;--c) p=PR(p,c);
fact(p);fact(n/p);
}
int Case,q[100],cnt,mod;ll n,k,p[100],ans;
int fpow(int x,ll y){
ll res=1;
while (y) {if (y&1) res=1ll*res*x%mod;x=1ll*x*x%mod;y>>=1;}
return res;
}
int g(ll n){return fpow(k,(n+1)>>1);}
int h(ll n){return (n&1?n:n>>1)%mod;}
void dfs(int i,ll d,int pro){
if (i==cnt+1){
if ((n/d&1)&&(d&1)==0) return;
ans=(ans+1ll*g(n/d)*h(n/d)%mod*pro)%mod;
return;
}
dfs(i+1,d,pro);pro=1ll*pro*(mod+1-p[i]%mod)%mod;
for (int j=1;j<=q[i];++j) d*=p[i],dfs(i+1,d,pro);
}
int main(){
srand(20020415);
scanf("%d",&Case);while (Case--){
scanf("%lld%lld%d",&n,&k,&mod);k%=mod;
len=cnt=0;fact(n);sort(tmp+1,tmp+len+1);
for (int i=1;i<=len;++i){
if (tmp[i]!=tmp[i-1]) p[++cnt]=tmp[i],q[cnt]=0;
++q[cnt];
}
ans=0;dfs(1,1,1);printf("%lld\n",ans);
}
return 0;
}

[BZOJ5330][SDOI2018]反回文串的更多相关文章

  1. BZOJ 5330 Luogu P4607 [SDOI2018]反回文串 (莫比乌斯反演、Pollard Rho算法)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330 (Luogu) https://www.luogu.org/prob ...

  2. [SDOI2018]反回文串

    题意 问有多少个长度为\(N\)且字符集大小为\(K\)的字符串可以通过回文串旋转 (把第一个字符移到最后)若干次得到.\(K\le N≤10^{18}\) 做法 ARC64F的加强版 设\(h(d) ...

  3. [BZOJ 5330][SDOI2018] 反回文串

    传送门 怎么说呢,一道不可多得的反演题吧,具体解释之后再补 #include <bits/stdc++.h> using namespace std; #define rep(i,a,b) ...

  4. 【SDOI2018】反回文串(【ARC064 F】Rotated Palindromes 加强版)

    题意 给你一个正整数 \(n\),求有多少字符集为 \(1\) 到 \(k\) 之间整数的字符串,使得该字符串可以由一个长度为 \(n\) 的回文串循环移位得到. ARC原题 \(100\%\) 的数 ...

  5. 「SDOI 2018」反回文串

    题目大意: 求字符集大小为$k$长度为$n$的经循环移位后为回文串的数量. 题解: 这题是D1里最神的吧 考虑一个长度为$n$回文串,将其循环移位后所有的串都是满足要求的串. 但是显然这样计算会算重. ...

  6. [luogu4607]反回文串

    参考ARC064F 令$h(n)=\begin{cases}n(n为奇数)\\\frac{n}{2}(n为偶数)\end{cases}$,$f(n)$定义与ARC064F相同,答案即$\sum_{d| ...

  7. [LeetCode] Longest Palindrome 最长回文串

    Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...

  8. [LeetCode] Shortest Palindrome 最短回文串

    Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...

  9. [LeetCode] Palindrome Partitioning II 拆分回文串之二

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

随机推荐

  1. Integration Services 变量

    如果没有变量,你会发现在ssis里面啥都干不成,和人没有灵魂一样 对系统变量唯一可配置的选项是指定变量在更改值时是否引发事件. 待续

  2. 中文乱码—Servlet—SpringMVC

    一.SpringMVC中的中文乱码问题 a:处理全局请求的中文乱码(配置Web.xml的字符编码过滤器) <filter> <filter-name>encodingFilte ...

  3. java集合框架体系

    Collection接口: 1.单列集合类的根接口. 2.定义了可用于操作List.Set的方法——增删改查: 3.继承自Iterable<E>接口,该接口中提供了iterator() 方 ...

  4. 文件名含中文的JavaWeb文件下载

    在javaweb项目中实现文件下载,当文件名中包含中文文字时,需要进行如下的处理,才能在浏览器端正常显示中文文件名: response.setContentType("octets/stre ...

  5. Linux内核分析08

    进程的切换和系统的一般执行过程 一,进程切换的关键代码switch_to分析 进程调度的时机 中断处理过程(包括时钟中断.I/O中断.系统调用和异常)中,直接调用schedule(),或者返回用户态时 ...

  6. 20145201李子璇 《网络对抗》MSF基础应用

    实践报告 MS08_067漏洞渗透攻击 ms11_050漏洞攻击 Adobe漏洞攻击 辅助模块应用(auxiliary/scanner/portscan/tcp漏洞) MS08_067漏洞渗透攻击实践 ...

  7. 20145219《网络对抗技术》PC平台逆向破解之逆向与Bof基础

    20145219<网络对抗技术>PC平台逆向破解之逆向与Bof基础 实践目标 实践对象:一个名为pwn1的linux可执行文件. pwn1正常执行流程:main调用foo函数,foo函数会 ...

  8. DataSet 和 DataTable 以及 DataRow

    向DataSet中添加DataTable 会提示datatable已属于另一个dataset 本来的想法是每次都new一个DataTable,但是还是会报错 百度了一下,发现可以调用DataTable ...

  9. 微信小程序登录,获取code,获取openid,获取session_key

    微信小程序登录 wx.login(Object object) 调用接口获取登录凭证(code).通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session ...

  10. mac上将代码上传到github以及github对100M以上文件限制上传的处理(lfs)。

    前言 有时我们会写一些小程序来学习新的知识,但是完事之后过一段时间可能会忘记,最好的办法就是找到原来的代码看一看.现在可以将代码免费托管到一些网站上,其中最著名的非github莫属了, 今天就把这个过 ...