「SDOI 2018」反回文串
题目大意:
求字符集大小为$k$长度为$n$的经循环移位后为回文串的数量。
题解:
这题是D1里最神的吧
考虑一个长度为$n$回文串,将其循环移位后所有的串都是满足要求的串。
但是显然这样计算会算重。考虑什么情况下会算重。
即当我们将这个回文串移位$x$后,发现这个新字符串为一个回文串时,必然接下来的移位都是重复的。
那么当$x$为多少时,新字符串为一个回文串?
我们稍加分析就会发现x一定和回文串的最小循环节$d$有关。
考虑最小循环节若为偶数时,当$x==d/2$时,则会变为一个新的回文串。
反之,$x==d$时,会出现一个新的回文串。
那么我们设$F(d)$表示长度为$n$,字符集为$k$,最小循环节为d的字符串的数量。
显然会有$\sum_{d|n}F(d)==k^{\lceil \frac{n}{2}\rceil}$。
设$G(n)=k^{\lceil \frac{n}{2}\rceil}$。
由莫比乌斯反演则有$F(d)=\sum_{n|d}\mu(\frac{n}{d})G(n)$。
那么考虑循环节$d$为偶数的串对答案贡献应该为$\frac{d}{2}*F(d)$这个我们在上面已经分析过了。
反之,则有其贡献为$d*F(d)$。
那么$Ans=\sum_{d|n}F(d)\frac{d}{1+[d为偶数]}$。
我们设$H(d)=\frac{d}{1+[d为偶数]}$。
观察这个式子,发现直接求对于$1e18$的数据显然会T。考虑继续优化。
发现算法瓶颈在于$H(dm)$,思考$\sum_{d|x}\mu(d)*H(dm)$的性质。
由于$H(dm)$的值与奇偶性有关,那么我们分类讨论一下$m$和$\frac{n}{m}$之间奇偶性的关系。
考虑对于四种情况,我们(可以经过打表或者推导)会发现,当$m$为奇数且$\frac{n}{m}$为偶数时,$\sum_{d|\frac{n}{m}}\mu(d)H(dm)$为0,而另外三种情况都是$H(m)\sum_{d|\frac{n}{m}}\mu(d)H(d)$。
代码:
#include "bits/stdc++.h" #define int long long using namespace std; inline int read () {
int s=0,k=1;char ch=getchar();
while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar();
while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar();
return s*k;
} typedef long long ll; inline ll R(ll x) {
return 1ll*rand()*rand()%x;
} inline ll Mult ( ll a,ll b ,ll mod) {
return ( a*b - (ll)( (long double) a*b/mod )*mod + mod )% mod;
} inline ll powmod(ll a,ll b,ll mod) {
ll ret=1;
while (b) {
if (b&1) ret = Mult(ret,a,mod);
b>>=1;a=Mult(a,a,mod);
}
return ret;
} int prim[] = {2,3,5,7,11}; inline int Miller_Rabin(ll n) {
if (n==2) return true;
int s=20,i,t=0;
for (i=0;i<5;++i)
if (n==prim[i]) return true;
else if (n%prim[i]==0) return false;
ll u=n-1,x[30];
while (!(u&1))
++t,u>>=1;
// printf("n=%lld u=%l\n",n);
while (s--) {
ll a=1ll*rand ()*rand()%(n-2)+2;
x[0] = powmod (a,u,n);
for (i=1;i<=t;++i) {
x[i] = Mult(x[i-1],x[i-1],n);
if (x[i]==1&&x[i-1]!=1&&x[i-1]!=n-1) return false;
}
if (x[t]!=1) return false ;
}
return true;
} inline ll gcd (ll a,ll b) {
return b?gcd(b,a%b):a;
} inline ll Pollard_Rho(ll n,int c) {
ll i=1,k=2,x=rand()%(n-1)+1,y=x;
// printf("n=%lld\n",n);
while (1) {
++i ;
x = (Mult(x,x,n) + c)%n;
ll p = gcd (y-x+n,n);
if (p!=1&&p!=n) return p;
if (y==x) return n;
if (i==k) {
y=x;
k<<=1;
}
}
} ll f[100],mod;
int cnt; inline void find(ll n) {
if (n==1) return ;
// printf("%lld\n",n);
if (Miller_Rabin(n)) {
f[++cnt]=n;
return ;
}
//while (n==13);
ll p=n;
while (p==n) p = Pollard_Rho(n,R(n-1));
// printf("p=%lld\n",p);
find(p);
find(n/p);
} ll n,k; int m,num[100];
ll p[100][100];
ll ans; inline void add (ll &x,ll y) {
x+=y;
//printf("x=%lld y=%lld mod=%lld\n",x,y,mod);
if (x>=mod) x-=mod;
if (x<0) x+=mod;
} inline void dfs(int step,ll d,ll S) {
if (step>m) {
if ((d&1)==0&&(n/d&1)) return ;
ll tmp=n/d;
//printf("tmp=%lld d=%lld\n",tmp,d);
//printf("k=%lld %lld %lld %lld\n",k,powmod(k,(tmp+1)/2,mod),((tmp&1)?tmp:tmp/2),S);
add ( ans , Mult(Mult(powmod(k,(tmp+1)/2,mod),((tmp&1)?tmp:tmp/2),mod),S,mod));
return ;
}
dfs (step+1,d,S);
for (int i=1;i<=num[step];++i)
dfs (step + 1, d*p[step][i],S*(1-p[step][1]));
//printf("step=%d\n",step);
} main ()
{
//freopen("3.in","r",stdin);
//freopen("3.out","w",stdout);
int T=read();
while (T--) {
scanf("%lld%lld",&n,&k),mod=read();
k%=mod;
cnt=m=0;
ans =0;
find(n);
sort(f+1,f+cnt+1);
memset(p,0,sizeof p);
for (int i=1,j=1;i<=cnt;i=j) {
p[++m][0]=1;
p[m][1]=f[i];
num[m]=1;
// printf("p=%lld\n",f[i]);
for (j=i+1;j<=cnt;++j)
if (f[j]!=f[j-1]) break;
else p[m][j-i+1]=p[m][j-i]*f[j];
num[m]=j-i;
// printf("num=%lld\n",num[m]);
}
dfs(1,1,1);
printf("%lld\n",ans);
}
return 0;
}
「SDOI 2018」反回文串的更多相关文章
- 「SDOI 2018」战略游戏
题目大意: 给一个$G=(V,E)$,满足$|V|=n$,$|E|=m$,且保证图联通,有Q个询问,每组询问有s个点,求图中有多少点满足:将其删去后,这s个点中存在一对点集$(a,b)$不联通且删去点 ...
- Solution -「SDOI 2018」「洛谷 P4606」战略游戏
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向连通图,\(q\) 次询问,每次给出一个点集 \(s\),求至少在原图中删去多 ...
- 「TJOI 2018」游园会 Party
「TJOI 2018」游园会 Party 题目描述 小豆参加了 \(NOI\) 的游园会,会场上每完成一个项目就会获得一个奖章,奖章只会是 \(N, O, I\) 的字样. 在会场上他收集到了 \(K ...
- LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)
写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...
- LOJ #2802. 「CCC 2018」平衡树(整除分块 + dp)
题面 LOJ #2802. 「CCC 2018」平衡树 题面有点难看...请认真阅读理解题意. 转化后就是,给你一个数 \(N\) ,每次选择一个 \(k \in [2, N]\) 将 \(N\) 变 ...
- LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)
题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- 「TJOI 2018」教科书般的亵渎
「TJOI 2018」教科书般的亵渎 题目描述 小豆喜欢玩游戏,现在他在玩一个游戏遇到这样的场面,每个怪的血量为 \(a_i\) ,且每个怪物血量均不相同, 小豆手里有无限张"亵渎" ...
随机推荐
- shc/unshc加/解密shell脚本
一.加密软件shcshc是linux的一款加密脚本的插件东西比较安全我们可以利用wget将文件放在root目录下也可以通过sftp放在root目录也可以直接利用cd命令选择目录一切随意shc官网:ht ...
- Spring Boot定时任务应用实践
在Spring Boot中实现定时任务功能,可以通过Spring自带的定时任务调度,也可以通过集成经典开源组件Quartz实现任务调度. 一.Spring定时器 1.cron表达式方式 使用自带的定时 ...
- FFMpeg编译之路
为了编译这个东西,快折腾了一个星期了.期间经历了很多痛苦的过程,今天我把整个过程,以及在这个过程的感悟写下来,以备日后查看,也希望能帮到一些像我一样的兄弟姐妹. 在这一个星期里前前后后加起来总共使用了 ...
- 手机号 验证函数 C++
直接上代码 #include <regex> bool IsValidPhoneNumber(const std::string& strPhone) { std::regex ...
- Jmeter——HTTP协议的接口压力测试环境搭建
文章版权由作者小小小丝和博客园共有,若转载请于明显处标明出处:http://rpc.cnblogs.com/metaweblog/xxxs JDK 是整个Java的核心,包括了Java运行环境.Ja ...
- java数据库之JDBC
任何一个项目,都离不开数据,而对于数据的存储以及其他操作,就会用到数据库了. 在这里是主要针对MySQL数据库的操作. 1.软件 当然首先要下载MySQL,为了操作起来更加方便,这里推荐一个比较方便的 ...
- Spark学习笔记
Map-Reduce 我认为上图代表着MapReduce不仅仅包括Map和Reduce两个步骤这么简单,还有两个隐含步骤没有明确,全部步骤包括:切片.转换.聚合.叠加,按照实际的运算场景上述步骤可以简 ...
- 四年级--python函数基础用法
一.函数的定义,调用和返回值 1.1 语法 def 函数(参数一,参数二...): ''' 文档注释 ''' 代码逻辑一 代码逻辑二 .... return 返回值 1.2 定义函数的三种形式 说明: ...
- JavaScript高级程序设计(一)
一.三种常见的著名的命名规则: 1.Camel(驼峰式命名):首字母是小写的,接下来的单词都以大写字母开头.例如:var myTestValue=0; 2.Pascal(帕斯卡命名):首字母是大写的 ...
- 第一课:Hadoop集群环境搭建
一. 检查列表 1.1.网络访问 设置电脑IP以及可以访问网络设置:进入etc/sysconfig/network-scripts/,使用命令"ls -all" 查看文件.会看到i ...