【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的要求的序列数量,答案对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;
}
时间: 2024-10-26 01:45:41

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

[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

[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 当然,直接生成函

【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取模. Sampl

[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

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

【bzoj4818】 Sdoi2017—序列计数

http://www.lydsy.com/JudgeOnline/problem.php?id=4818 (题目链接) 题意 一个长度为$n$的序列,每个元素是不超过$m$的正整数,且这$n$个数的和是$p$的倍数,这$n$个数中至少有一个是质数,问这样的序列有多少个. Solution md吓死我了,还以为想错了,$p^2\log n$的半天不敢写=.= $f[i][j]$表示忽略质数条件下的长度为$i$,和$mod~p=j$的序列数:$g[i][j]$表示满足没有一个数是质数的情况下长度为$

BZOJ 4818 SDOI2017 序列计数

刚出炉的省选题,还是山东的. 自古山东出数学和网络流,堪称思维的殿堂,比某地数据结构成风好多了. 废话不说上题解. 1.题面 求:n个数(顺序可更改),值域为[1,m],和为p的倍数,且这些树里面有质数的方案数是多少? 解题报告: 0% O(n^n)爆搜,没什么好讲的,用来拍DP: #include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #define LL

【[SDOI2017]序列计数】

感觉自己的复杂度感人 大概是\(O(p*\pi(m)+p^3logn)\) 还是能过去的 我们看到这么大的数据范围还是应该先想一想暴力怎么写 显然我们可以直接暴力\(dp\) 设\(dp[i][j]\)表示已经选择了\(i\)数,其中所有数的和\(mod\ p\)为\(j\)的方案数 显然方程是 \[f[i][j]=\sum_{k=1}^mdp[i-1][((j-k)\%p+p)\%p]\] 初始的状态是\(dp[0][0]=1\),最终的答案是\(dp[n][0]\) 至于还有一个至少有一个素