【[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想知道,有多少个序 ...
随机推荐
- MySQL---2、安装与部署
1.MySQL下载 MySQL版本的选择MySQL Community Server 社区版本,开源免费,但不提供官方技术支持.MySQL Enterprise Edition 企业版本,需付费,可以 ...
- 一:XML知识整理
一:xml 1. xml简介 a) xml, eXtensible Markup Language, 可扩展标记语言.是一种标记语言. b) xml 是一种非常灵活的语言, 没有固定的标签, 所有的标 ...
- 一、hive安装(内置数据库derby)
hive是一个数据仓库工具,建立在hadoop之上,它的存在是为了让大数据的查询和分析更加的方便.hive提供简单的sql查询功能,并最终转换为mapreduce任务执行. 一.环境 JDK1.8+官 ...
- linux ubuntu 安装nginx
参考原文 在Ubuntu下安装Nginx有以下方法,但是如果想要安装最新版本的就必须下载源码包编译安装. 一.基于APT源安装 sudo apt-get install nginx 安装好的文件位置: ...
- centos 6无法上外网
1.先配置/etc/sysconfig/network-scripts/ifcfg-eth0 配置完成后能ping通内网.网关,但是上不了外网 DEVICE=eth0 HWADDR=:0C::FF:: ...
- C#语言总结1
C#C#定义: C#是一门面向对象.面向组件的一门语言,是.NET的一部分. 程序结构: 命名空间 类{ 属性 方法 main函数入口 } 数据类型: C#的数据类型分为:值类型(Value type ...
- 【零基础学习FreeRTOS嵌入式系统】之一:FreeRTOS环境搭建
[零基础学习FreeRTOS嵌入式系统]之一:FreeRTOS环境搭建 一:FreeRTOS系统下载 在官网上https://www.freertos.org/,找到下载入口. 或直接进入下载地址ht ...
- 关于this的全面解析(call,apply,new)
我们在写代码的时候,时常会被this弄的傻傻分不清楚,看源码的时候也经常被call啊apply啊弄的头皮发麻.this到底是什么?本文主要根据书上和实际应用做了一些归纳.一般情况下this有4种绑定规 ...
- jQuery轮播图(一)轮播实现并封装
利用面向对象自己动手写了一个封装好的jquery轮播组件,可满足一般需求,不仅使用简单且复用性高. demo:点此预览 代码地址:https://github.com/zsqosos/componen ...
- Scratch GUI
原文地址:https://github.com/LLK/scratch-gui/wiki/Getting-Started Getting Started Bryce Taylor edited t ...