【BZOJ4818】[Sdoi2017]序列计数 DP+矩阵乘法

【BZOJ4818】[Sdoi2017]序列计数

Description

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

,这n个数中,至少有一个数是质数。Alice想知道,有多少个序列满足她的要求。

Input

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

1<=n<=10^9,1<=m<=2×10^7,1<=p<=100

Output

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

Sample Input

3 5 3

Sample Output

33

题解:至少包含1个质数的数量=总数-不包含质数的数量 (这种补集法不是一次两次见到了吧?)

于是我们考虑用DP求解,先快筛出1..m内的质数,1..m内除以P模为j的数的个数,1..m内除以P模为j的合数的个数

然后设f[i][j]表示i个数,总和除以P模j的方案数,g[i][j]表示i个合数,总和除以P模j的方案数,容易得出

f[i+1][(j+k)%P]+=f[i][j]+1..m内除以P模为j的数的个数
g[i+1][(j+k)%P]+=g[i][j]+1..m内除以P模为j的合数的个数

发现时间复杂度O(np),用矩乘快速幂优化一下就好啦

#include <cstdio>
#include <cstring>
#include <iostream>
#define mod 20170408
using namespace std;
typedef long long ll;
int np[20000010],cnt[110],sum[110],pri[10000010];
int n,m,p,tot;
typedef struct matrix
{
	ll v[110][110];
}M;
M x,ans,emp;
ll ans1;
M mmul(M a,M b)
{
	M c=emp;
	int i,j,k;
	for(i=0;i<p;i++)
		for(j=0;j<p;j++)
			for(k=0;k<p;k++)
				c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%mod;
	return c;
}
void pm(int y)
{
	while(y)
	{
		if(y&1)	ans=mmul(ans,x);
		x=mmul(x,x),y>>=1;
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&p);
	int i,j;
	np[1]=cnt[1]=sum[1]=1;
	for(i=2;i<=m;i++)
	{
		sum[i%p]=(sum[i%p]+1)%mod;
		if(!np[i])	pri[++tot]=i;
		else	cnt[i%p]=(cnt[i%p]+1)%mod;
		for(j=1;j<=tot&&i*pri[j]<=m;j++)
		{
			np[i*pri[j]]=1;
			if(i%pri[j]==0)	break;
		}
	}
	for(i=0;i<p;i++)
		for(j=0;j<p;j++)
			x.v[i][(i+j)%p]=(x.v[i][(i+j)%p]+sum[j])%mod;
	ans.v[0][0]=1;
	pm(n);
	ans1=ans.v[0][0];
	memset(ans.v,0,sizeof(ans.v)),memset(x.v,0,sizeof(x.v));
	ans.v[0][0]=1;
	for(i=0;i<p;i++)
		for(j=0;j<p;j++)
			x.v[i][(i+j)%p]=(x.v[i][(i+j)%p]+cnt[j])%mod;
	pm(n);
	printf("%lld",(ans1-ans.v[0][0]+mod)%mod);
	return 0;
}
时间: 2024-11-03 22:35:24

【BZOJ4818】[Sdoi2017]序列计数 DP+矩阵乘法的相关文章

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

[Sdoi2017]序列计数 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=4818. 题解: 首先列出来一个递推式子 $f[i][0]$表示$i$个任意数的答案. $f[i][1]$表示$i$个合数的答案. 转移的时候发现可以用矩阵优化这个过程. 至于怎么把矩阵建出来,我们可以开个桶来解决这个问题. 代码: #include <bits/stdc++.h> using namespace std; typedef long lon

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

Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ,这n个数中,至少有一个数是质数.Alice想知道,有多少个序列满足她的要求. Input 一行三个数,n,m,p. 1<=n<=10^9,1<=m<=2×10^7,1<=p<=100 Output 一行一个数,满足Alice的要求的序列数量,答案对20170408取模. Sample Input 3 5 3 Sample Outp

loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)

题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i + 1][(j + k) \% p] += f[i][j]\) 矩乘优化一下. #include<bits/stdc++.h> #define LL long long using namespace std; const int MAXN = 2e7 + 10, mod = 20170408,

[bzoj4818][Sdoi2017]序列计数

来自FallDream,未经允许,请勿转载,谢谢.  Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望,这n个数中,至少有一个数是质数.Alice想知道,有多少个序列满足她的要求.答案取模20170408 n<=10^9 m<=2*10^7 p<=100 题解:考虑计算任意选择的答案 然后把质数去掉,再算一次答案,求差即可. 然后这道题数据范围好水啊 p只有100  瞎矩阵乘法都能过 那个要k^3logn 当然,直接生成函

[Sdoi2017]序列计数

4818: [Sdoi2017]序列计数 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 317  Solved: 210 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数.Alice还希望 ,这n个数中,至少有一个数是质数.Alice想知道,有多少个序列满足她的要求. Input 一行三个数,n,m,p. 1<=n<=10^9,1<=m<=2×10^7,1<

P3702 [SDOI2017]序列计数

P3702 [SDOI2017]序列计数 链接 分析: 代码: #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map

『公交线路 状压dp 矩阵乘法加速』

公交线路 Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计线路: 1.设共K辆公交车,则1到K号站作为始发站,N-K+1到N号台作为终点站. 2.每个车站必须被一辆且仅一辆公交车经过(始发站和终点站也算被经过). 3.公交车只能从编号较小的站台驶往编号较大的站台. 4.一辆公交车经过的相邻两个 站台间距离不得超过Pkm. 在最终设计

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

原文地址: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的要求的序列数量,答案对2017

BZOJ 3329 Xorequ 数位DP+矩阵乘法

题目大意:给定n,求[1,n]以内以及[1,2^n]以内有多少x满足x^3x=2x x^3x=2x等价于x^2x = 3x 而3x=x+2x 且2x=x<<1 故x满足条件当且仅当x&(x<<1)=0 故x的二进制拆分中任意两个1不相邻 令f[i]为i位数中最高位为0的满足条件的数的数量 g[i]为i位数中最高位为1的满足条件的数的数量 则显然有 f[i+1]=f[i]+g[i] g[i+1]=f[i] 于是第一问数位DP 第二问矩阵乘法即可 #include <cs