原文地址:http://www.cnblogs.com/GXZlegend/p/6825132.html


题目描述

Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数。Alice还希望,这n个数中,至少有一个数是质数。Alice想知道,有多少个序列满足她的要求。

输入

一行三个数,n,m,p。
1<=n<=10^9,1<=m<=2×10^7,1<=p<=100

输出

一行一个数,满足Alice的要求的序列数量,答案对20170408取模。

样例输入

3 5 3

样例输出

33


题解

矩阵乘法

至少有1个质数的方案数=总方案数-不含质数的方案数

可以先在O(m)的时间内把1~m的质数筛出来。

然后考虑:从mod p=0,到mod p=0,可以由mod p=a和mod p=p-a两个阶段组成。

可以设f[i][j]表示从mod p=i到mod p=j的方案数,不难看出这是一个矩阵,而且自乘m次就能得到答案。

所以只要处理出2种f即可。

对于每个数可以更新所有的f[i](0≤i<n),不过这样会TLE

其实这样做没有必要,因为f都是循环出现的,只需要求f[0]即可,再据此推其余的f。

代码中,我将mod p=0当作了p来处理,其实看作0也是一样的。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define mod 20170408
using namespace std;
typedef long long ll;
bool notprime[20000010];
int pri[5000010] , top;
struct matrix
{
int n , m;
ll num[110][110];
matrix()
{
n = m = 0;
memset(num , 0 , sizeof(num));
}
matrix operator*(const matrix a)const
{
matrix ans;
ans.n = n , ans.m = a.m;
int i , j , k;
for(i = 1 ; i <= ans.n ; i ++ )
for(j = 1 ; j <= ans.m ; j ++ )
for(k = 1 ; k <= m ; k ++ )
ans.num[i][j] = (ans.num[i][j] + num[i][k] * a.num[k][j]) % mod;
return ans;
}
}A , B;
matrix pow(matrix x , int y)
{
matrix ans;
int i;
ans.n = x.n , ans.m = x.m;
for(i = 1 ; i <= ans.n ; i ++ )
ans.num[i][i] = 1;
while(y)
{
if(y & 1) ans = ans * x;
x = x * x , y >>= 1;
}
return ans;
}
int main()
{
int n , m , p , i , j;
scanf("%d%d%d" , &n , &m , &p);
notprime[1] = 1;
for(i = 2 ; i <= m ; i ++ )
{
if(!notprime[i]) pri[++top] = i;
for(j = 1 ; j <= top && i * pri[j] <= m ; j ++ )
{
notprime[i * pri[j]] = 1;
if(i % pri[j] == 0) break;
}
}
A.n = A.m = B.n = B.m = p;
for(i = 1 ; i <= m ; i ++ )
{
A.num[p][(i - 1) % p + 1] ++ ;
if(notprime[i]) B.num[p][(i - 1) % p + 1] ++ ;
}
for(i = p - 1 ; i >= 1 ; i -- )
for(j = 1 ; j <= p ; j ++ )
A.num[i][j] = A.num[i + 1][j % p + 1] , B.num[i][j] = B.num[i + 1][j % p + 1];
printf("%lld\n" , (pow(A , n).num[p][p] - pow(B , n).num[p][p] + mod) % mod);
return 0;
}

【bzoj4818】[Sdoi2017]序列计数 矩阵乘法的更多相关文章

  1. BZOJ 4818 [Sdoi2017]序列计数 ——矩阵乘法

    发现转移矩阵是一个循环矩阵. 然后循环矩阵乘以循环矩阵还是循环矩阵. 据说还有FFT并且更优的做法. 之后再看吧 #include <map> #include <cmath> ...

  2. luogu 3702 [SDOI2017]序列计数 矩阵乘法+容斥

    现在看来这道题真的不难啊~ 正着求不好求,那就反着求:答案=总-全不是质数 这里有一个细节要特判:1不是质数,所以在算全不是质数的时候要特判1 code: #include <bits/stdc ...

  3. [bzoj4818][Sdoi2017]序列计数_矩阵乘法_欧拉筛

    [Sdoi2017]序列计数 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=4818. 题解: 首先列出来一个递推式子 $f[i][0]$ ...

  4. [Sdoi2017]序列计数 [矩阵快速幂]

    [Sdoi2017]序列计数 题意:长为\(n \le 10^9\)由不超过\(m \le 2 \cdot 10^7\)的正整数构成的和为\(t\le 100\)的倍数且至少有一个质数的序列个数 总- ...

  5. [BZOJ 4818/LuoguP3702][SDOI2017] 序列计数 (矩阵加速DP)

    题面: 传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4818 Solution 看到这道题,我们不妨先考虑一下20分怎么搞 想到暴力,本蒟 ...

  6. [BZOJ4818][SDOI2017]序列计数(动规+快速幂)

    4818: [Sdoi2017]序列计数 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 972  Solved: 581[Submit][Status ...

  7. 【BZOJ4818】【SDOI2017】序列计数 [矩阵乘法][DP]

    序列计数 Time Limit: 30 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Alice想要得到一个长度为n的序 ...

  8. 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)

    传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...

  9. BZOJ4818 [SDOI2017] 序列计数 【矩阵快速幂】

    题目分析: 一个很显然的同类项合并.注意到p的大小最大为100,考虑把模p意义下相同的求出来最后所有的减去没有质数的做矩阵快速幂即可. 代码: #include<bits/stdc++.h> ...

随机推荐

  1. 解决 Jsp_Servlet 编码乱码问题

    Tomcat8.0以上浏览器请求的数据编码格式(包含): Get请求的时候Tomcat用UTF-8处理 post请求的时候Tomcat用ISO8859-1处理 Tomcat8.0以下浏览器请求的数据编 ...

  2. Element表单验证(1)

    Element表单验证(1) 首先要掌握Element官方那几个表单验证的例子,然后才看下面的教程. Element主要使用了async-validator这个库作为表单验证 async-valida ...

  3. scoped,会使设置UI组件库的样式识别不出来

    未设置 scoped 作用域:显示效果 设置作用域的效果:ui组件默认的值(你怎么设置都不管用)

  4. java.lang.UnsupportedOperationException: Exception occurred during processing request: null

    1.Action有问题,Struts2注解拼写错误,注解包版本不匹配! 2.今天还有一个错误,Tomcat服务器异常,无法启动,Remove/clean后还是无法启动 :极大可能是web.xml 写错 ...

  5. Spring框架进阶3

    Spring框架进阶3 测试spring_jdbc和spring对事务的管理 先配置相应的pom <?xml version="1.0" encoding="UTF ...

  6. linux系统的启动过程简要分析

    接触linux系统运维已经好几年了,常常被问到linux系统启动流程问题,刚好今天有空来梳理下这个过程:一般来说,所有的操作系统的启动流程基本就是: 总的来说,linux系统启动流程可以简单总结为以下 ...

  7. tcl之过程/函数-proc

  8. C语言数组篇(二)指针数组和数组指针

    数组指针 和 指针数组         这两个名词可以说是经常搞混了         数组指针--> 数组的指针       就是前面讲的 指向数组a的指针p;         指针数组--&g ...

  9. debug注意事项

    1 先看关键代码是否正确,然后查一遍是否有变量名打错. 2 再看初始化有没有问题 3 再把范围开大和开int64(这应该刚开始看题就要注意,在不爆内存的情况下开int64) 4 静态调试,输出中间值. ...

  10. 利用js实现倒计时

    倒计时 这个名词并不陌生,比如:天猫,京东等一些网上商城都会推出一些限时特价商品,今天我们就一起编写一个属于自己的倒计时: Ps: 首先做一件事情的时候,不应该盲目的去做,应该首当其冲的去想,脑子里面 ...