题面

Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数。

Alice还希望,这n个数中,至少有一个数是质数。

Alice想知道,有多少个序列满足她的要求。

输入格式

一行三个数,n,m,p。

对100\%的数据,1<= n <=1e9,1<= m <= 2e7,1<= p <= 100

输出格式

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

题解

我很少写这样的矩阵快速幂的题解

由于p的范围很小,所以p^3*log是可以过的

我们先求不加质数限制的方案数,再减去所有数都为合数的方案。

这道题,其实我们要知道[1,m]中的这些数在p的剩余系中的分布就可以计算,

因为对于不加质数限制的方案,就算值域在[1 + p,m + p]它的答案也是正确的。

设f[i][j]表示对于i个数,“ 其总和 % p = j ”的方案数,

我们发现,对于f,余数是要相加的,而方案数是要相乘的,

根据这个来推一下矩阵,i = 1的情况要直接算:

然后答案矩阵 ,这里的n就是题目中的n,

再来推一下所有数都是合数的方案

其实只要用欧拉筛筛一遍合数就行,然后:

表示对于i个合数,“ 其总和 % p = j ”的方案数,

我们发现,对于f,余数是要相加的,而方案数是要相乘的,

根据这个来推一下矩阵,i = 1的情况要直接算:

然后答案矩阵 ,这里的n就是题目中的n,

最终的答案就是

别忘了要全程取模

CODE

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<algorithm>
#define LL long long
#define MAXN 200005
#pragma GCC optimize(2)
#pragma G++ optimize(3)
#define rg register
#define DB double
using namespace std;
inline int read() {
int f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
return x * f;
}
int mod = 20170408;
int n,m,q,i,j,s,o,k,t;
struct matrix{
int n,m;
int a[105][105];
matrix(){memset(a,0,sizeof(a));n = m = 1;}
}m1;
matrix operator * (matrix A,matrix B) {
matrix C;
C.n = A.n;C.m = B.m;
for(rg int i = 1;i <= C.n;i ++) {
for(rg int k = 1;k <= A.m;k ++) {
for(rg int j = 1;j <= C.m;j ++) {
C.a[i][j] = (C.a[i][j] + A.a[i][k] *1ll* B.a[k][j] % mod) % mod;
}
}
}
return C;
}
matrix qkpow(matrix a,LL b) {
if(b == 0) return m1;
if(b == 1) return a;
matrix as = qkpow(a,b>>1);
return as*as*qkpow(a,b&1);
}
int pri[5000005],cn;
bool f[20000005];
void sieve(int n) {
f[1] = 1;cn = 0;
for(rg int i = 2;i <= n;i ++) {
if(!f[i]) pri[++cn] = i;
for(rg int j = 1;j <= cn && i * pri[j] <= n;j ++) {
f[i * pri[j]] = 1;
if(i % pri[j] == 0) break;
}
}
}
int cnt[105],cnt2[105];
int main() {
n = read();m = read();k = read();
for(rg int i = 1;i <= k;i ++) m1.a[i][i] = 1;
m1.n = m1.m = k;
sieve(m);
for(rg int i = 1;i <= m;i ++) {
if(f[i]) cnt2[i % k] ++;
cnt[i % k] ++;
}
matrix A,B,C,D;
A.n = 1,A.m = B.n = B.m = k;
for(rg int i = 1;i <= k;i ++) A.a[1][i] = cnt[i-1];
for(rg int i = 1;i <= k;i ++) {
for(rg int j = 1;j <= k;j ++) {
B.a[j][i] = cnt[(k + i - j) % k];
}
}
C = A * qkpow(B,n-1);
A.n = 1,A.m = B.n = B.m = k;
for(rg int i = 1;i <= k;i ++) A.a[1][i] = cnt2[i-1];
for(rg int i = 1;i <= k;i ++) {
for(rg int j = 1;j <= k;j ++) {
B.a[j][i] = cnt2[(k + i - j) % k];
}
}
D = A * qkpow(B,n-1);
printf("%d\n",(C.a[1][1] + mod - D.a[1][1]) % mod);
return 0;
}

[SDOI2017]序列计数 (矩阵加速,小容斥)的更多相关文章

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

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

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

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

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

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

  4. 【bzoj4818】[Sdoi2017]序列计数 矩阵乘法

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825132.html 题目描述 Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的 ...

  5. Luogu3702 SDOI2017 序列计数 矩阵DP

    传送门 不考虑质数的条件,可以考虑到一个很明显的$DP:$设$f_{i,j}$表示选$i$个数,和$mod\ p=j$的方案数,显然是可以矩阵优化$DP$的. 而且转移矩阵是循环矩阵,所以可以只用第一 ...

  6. [Sdoi2017]序列计数 矩阵优化dp

    题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4818 思路 先考虑没有质数限制 dp是在同余系下的,所以\(f[i][j]\)表示前i个点, ...

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

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

  8. 【BZOJ 4818】 4818: [Sdoi2017]序列计数 (矩阵乘法、容斥计数)

    4818: [Sdoi2017]序列计数 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 560  Solved: 359 Description Al ...

  9. BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法

    BZOJ_4818_[Sdoi2017]序列计数_矩阵乘法 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ...

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

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

随机推荐

  1. 爬取豆瓣TOP250电影

    自己跟着视频学习的第一个爬虫小程序,里面有许多不太清楚的地方,不如怎么找到具体的电影名字的,那么多级关系,怎么以下就找到的是那个div呢? 诸如此类的,有许多,不过先做起来再说吧,后续再取去弄懂. i ...

  2. 【NOIP2017 提高组正式赛】列队 题解

    题目大意 有一个 \(n\times m\) 的方阵,每次有 \((x,y)\) 离开,离开后有两个命令 向左看齐.这时第一列保持不动,所有学生向左填补空缺.这条指令之后,空位在第 \(x\) 行第 ...

  3. JZOJ5384. 【NOIP2017提高A组模拟9.23】四维世界

    题目 Description 众所周知,我们常感受的世界是三维的. Polycarp突然对四维空间产生了兴趣,他想对四维空间进行一些研究.但是在此之前,他必须先对三维世界了解透彻. 于是Polycar ...

  4. opencv-python获取视频信息

    代码 import cv2 if __name__ == '__main__': # 读取视频 capture = cv2.VideoCapture('./videos/person.mp4') # ...

  5. 【机器学习】数据准备--python爬虫

    前言 我们在学习机器学习相关内容时,一般是不需要我们自己去爬取数据的,因为很多的算法学习很友好的帮助我们打包好了相关数据,但是这并不代表我们不需要进行学习和了解相关知识.在这里我们了解三种数据的爬取: ...

  6. RPA应用场景-产品主数据同步

    场景概述 产品主数据同步 所涉系统名称 产品管理系统.SAP系统 人工操作(时间/次) 35分钟 所涉人工数量 3 操作频率 不定时 场景流程1.登录收购品牌产品管理系统 2.根据时间.产品分类等选择 ...

  7. Linux文本查看工具

    文本查看工具 cat 特点: 不能用来看二进制文件 选项: -A: 显示不可见字符 cat支持标准输入: cat > aa.txt ---键盘作为标准输入,输出的结果重定向文件中去了 cat & ...

  8. python之多进程and多线程

    图文来自互联网 一.什么是进程和线程 (https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 进程是分配资源的最小单位,线程是系统调度的最小单位. 当应用程序运行时最 ...

  9. 详解HashMap源码解析(上)

    jdk版本:1.8 数据结构: HashMap的底层主要基于数组+链表/红黑树实现,数组优点就是查询块,HashMap通过计算hash码获取到数组的下标来查询数据.同样也可以通过hash码得到数组下标 ...

  10. 《ASP.NET Core 6框架揭秘》样章[200页/5章]

    作为<ASP.NET Core 3 框架揭秘>的升级版,<ASP.NET Core 6框架揭秘>不仅针对ASP.NET Core 6的新特性进行了修订,并添加了若干原来没有的内 ...