【[SDOI2017]序列计数】
感觉自己的复杂度感人
大概是\(O(p*\pi(m)+p^3logn)\)
还是能过去的
我们看到这么大的数据范围还是应该先想一想暴力怎么写
显然我们可以直接暴力\(dp\)
设\(dp[i][j]\)表示已经选择了\(i\)数,其中所有数的和\(mod\ p\)为\(j\)的方案数
显然方程是
\]
初始的状态是\(dp[0][0]=1\),最终的答案是\(dp[n][0]\)
至于还有一个至少有一个素数的限制条件,我们可以先不管这个条件直接算一遍,之后再保证\(k\)不为素数再算一遍,两个一减就是答案了
这样暴力转移的复杂度是\(O(nmp)\)的,于是我们要考虑优化
这个转移相当的固定,于是可以矩乘优化
我们发现因为\(p\)非常的小,于是那个膜\(p\)意义下的转移会有很多重复的位置被转移过去,于是我们如果可以预处理出这样一个数组\(tot[j][k]\)
表示\(dp[i-1][k]\)会向\(dp[i][k]\)专一多少次,也就是\(dp[i][k]+=dp[i-1][j]*tot[j][k]\)
于是就有这样一个矩阵会被构造出来

(\(p=3\)的情况)
于是就可以转移了,至于\(tot[j][k]\)怎么求,这个就是很简单了
在没有素数的情况下把所有素数对应的转移减一遍就好了
代码
#include<iostream>
#include<cstring>
#include<bitset>
#include<cstdio>
#define re register
#define maxn 20000005
#define LL long long
const LL mod=20170408;
std::bitset<maxn> f;
int prime[1500000];
LL ans[101][101],a[101][101];
int m,p;
LL n;
inline void did_a()
{
LL mid[101][101];
for(re int i=1;i<=p;i++)
for(re int j=1;j<=p;j++)
mid[i][j]=a[i][j],a[i][j]=0;
for(re int i=1;i<=p;i++)
for(re int j=1;j<=p;j++)
for(re int k=1;k<=p;k++)
a[i][j]=(a[i][j]+(mid[i][k]*mid[k][j])%mod)%mod;
}
inline void did_ans()
{
LL mid[101][101];
for(re int i=1;i<=p;i++)
for(re int j=1;j<=p;j++)
mid[i][j]=ans[i][j],ans[i][j]=0;
for(re int i=1;i<=p;i++)
for(re int j=1;j<=p;j++)
for(re int k=1;k<=p;k++)
ans[i][j]=(ans[i][j]+(mid[i][k]*a[k][j])%mod)%mod;
}
inline void Rebuild()
{
memset(ans,0,sizeof(ans));
memset(a,0,sizeof(a));
for(re int i=1;i<=p;i++)
ans[i][i]=1;
int t=m/p;
for(re int i=1;i<=p;i++)
for(re int j=1;j<=p;j++)
a[i][j]=t;
int tot=m%p;
for(re int i=1;i<=p;i++)
{
int cnt=tot,x=i-1;
if(!x) x=p;
while(cnt)
{
a[i][x]++,cnt--;
x--;
if(!x) x=p;
}
}
}
inline void out()
{
for(re int i=1;i<=p;i++)
{
for(re int j=1;j<=p;j++)
printf("%d ",a[i][j]);
putchar(10);
}
}
inline void quick(LL b)
{
while(b)
{
if(b&1ll) did_ans();
b>>=1ll;
did_a();
}
}
int main()
{
scanf("%lld%d%d",&n,&m,&p);
f[1]=1;
for(re int i=2;i<=m;i++)
{
if(!f[i]) prime[++prime[0]]=i;
for(re int j=1;j<=prime[0]&&prime[j]*i<=m;j++)
{
f[prime[j]*i]=i;
if(i%prime[j]==0) break;
}
}
Rebuild();
quick(n);
LL num=ans[1][1];
Rebuild();
for(re int i=1;i<=p;i++)
{
for(re int j=1;j<=prime[0];j++)
{
a[i][((i-1-prime[j])%p+p)%p+1]--;
if(a[i][(i-prime[j]+p)%p+1]<0) a[i][(i-prime[j]+p)%p+1]=mod-1;
}
}
quick(n);
std::cout<<(num-ans[1][1]+mod)%mod;
return 0;
}
【[SDOI2017]序列计数】的更多相关文章
- [Sdoi2017]序列计数 [矩阵快速幂]
[Sdoi2017]序列计数 题意:长为\(n \le 10^9\)由不超过\(m \le 2 \cdot 10^7\)的正整数构成的和为\(t\le 100\)的倍数且至少有一个质数的序列个数 总- ...
- BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法
BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ...
- 【BZOJ 4818】 4818: [Sdoi2017]序列计数 (矩阵乘法、容斥计数)
4818: [Sdoi2017]序列计数 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 560 Solved: 359 Description Al ...
- P3702 [SDOI2017]序列计数
P3702 [SDOI2017]序列计数 链接 分析: 首先可以容斥掉,用总的减去一个质数也没有的. 然后可以dp了,f[i][j]表示到第i个数,和在模p下是j的方案数,矩阵快速幂即可. 另一种方法 ...
- 【BZOJ4818】[Sdoi2017]序列计数 DP+矩阵乘法
[BZOJ4818][Sdoi2017]序列计数 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ,这n个数 ...
- BZOJ4818 LOJ2002 SDOI2017 序列计数 【矩阵快速幂优化DP】*
BZOJ4818 LOJ2002 SDOI2017 序列计数 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数. Alice还希 ...
- [BZOJ4818][SDOI2017]序列计数(动规+快速幂)
4818: [Sdoi2017]序列计数 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 972 Solved: 581[Submit][Status ...
- [bzoj4818][Sdoi2017]序列计数_矩阵乘法_欧拉筛
[Sdoi2017]序列计数 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=4818. 题解: 首先列出来一个递推式子 $f[i][0]$ ...
- [BZOJ 4818/LuoguP3702][SDOI2017] 序列计数 (矩阵加速DP)
题面: 传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4818 Solution 看到这道题,我们不妨先考虑一下20分怎么搞 想到暴力,本蒟 ...
- bzoj4818 [Sdoi2017]序列计数
Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望,这n个数中,至少有一个数是质数.Alice想知道,有多少个序 ...
随机推荐
- easyui多选与接收不一致解决方案
附代码: function batchRefund(){ if(editIndex != undefined) { $('#refundList').datagrid('endEdit', editI ...
- 微信小程序(一)--简单的介绍
转自:https://developers.weixin.qq.com/miniprogram/dev/index.html 响应的数据绑定 框架的核心是一个响应的数据绑定系统. 整个小程序框架系统分 ...
- WPF实现的简单饼图
简介 前段时间帮一个同事的忙,利用WPF实现的一个简单饼图,仅能看饼图的比例,无文字查看功能.效果图如下: 用法: var sectorParts = new List<SectorPart&g ...
- centos关闭selinux
SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统.在这种访问控制体系的限制下,进程只能访问那 ...
- Java编程基础知识总结大全(Ⅱ)
7.类型转换 精度从高到低 double float long int short(char) byte (1)自动类型转换 将一个低精度---高精度 (2)强制类型转换 将一个高精度---低精度 ...
- Bash on windows从14.0升级到ubuntu16.04
升级参考:https://www.zhihu.com/question/49411626 解决中文乱码问题参考:http://www.lofter.com/tag/ubuntu%E5%AD%90%E7 ...
- Java基础之java的四大特性
上篇文章说了jdk的安装和java环境的配置,这篇文章主要说下java的特性. 首相说下,编程语言分为面向过程和面向对象,而java就是一种面向对象的编程语言. 什么是面向过程编程呢?就是一流程为单位 ...
- mysql 中优化数据类型的三个原则
数据类型越小越好 在业务够用的情况下,尽可能选取小的数据类型.不仅占用空间小,而且执行查询等操作时性能好. 越简单越好 对于简单的类型,在处理时会占用更少的 CPU 周期. 例如,整数就比字符类型简单 ...
- 解决:IDEA 中 new Java Class 怎么没了?
前言:写代码时遇到的问题,所以记录下来.我的包名为“interface”,只有这个包及包下的文件不能建java文件. 问题 解决方式(对于普通包名) 点击应用,ok就可以了. 解决方式(对于包名为“i ...
- Http Status Code 套餐合集(转载)
1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 100(继续)请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101(切换协议)请求者已要 ...