DTOJ #3160. 序列计数(count)

【题目描述】

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

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

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

【输入格式】

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

【输出格式】

一行一个数,满足Alice的要求的序列数量。由于满足条件的序列可能很多,输出结果对 $20170408$ 取模。

【样例】

样例输入
3 5 3

样例输出
33

【数据范围与提示】

对于 $ 20 \% $ 的数据, $ 1 \le n \le 100,1 \le m \le 100 $。

对于 $ 50 \% $ 的数据, $ 1 \le m \le 100 $。

对于 $ 80 \% $ 的数据, $ 1 \le m \le 10^6 $。

对于 $ 100 \% $ 的数据, $ 1 \le n \le 10^9,1 \le m \le 2 \times 10^7,1 \le p \le 100 $。

【题解】

设 $f[i][j][0/1]$ 表示前 $i$ 个数,和在 $mod \ p$ 意义下为 $j$,是否取了质数的方案数。

列出转移式后用矩阵快速幂或多项式优化即可。

【代码】

#include<bits/stdc++.h>
const int mod=20170408;
int n,m,p,pr[20000010],tot;
bool flag[20000010];
struct Poly
{
    int a[110];
    inline friend Poly operator + ( const Poly &p1,const Poly &p2 )
    {
        Poly p3;memset(p3.a,0,sizeof(p3.a));
        for ( int i=0;i<p;i++ ) p3.a[i]=(p1.a[i]+p2.a[i])%mod;
        return p3;
    }
    inline friend Poly operator - ( const Poly &p1,const Poly &p2 )
    {
        Poly p3;memset(p3.a,0,sizeof(p3.a));
        for ( int i=0;i<p;i++ ) p3.a[i]=(p1.a[i]-p2.a[i]+mod)%mod;
        return p3;
    }
    inline friend Poly operator * ( const Poly &p1,const Poly &p2 )
    {
        Poly p3;memset(p3.a,0,sizeof(p3.a));
        for ( int i=0;i<p;i++ ) for ( int j=0;j<p;j++ ) p3.a[(i+j)%p]=(p3.a[(i+j)%p]+1LL*p1.a[i]*p2.a[j])%mod;
        return p3;
    }
    inline friend Poly operator ^ ( Poly p,int n )
    {
        Poly res;memset(res.a,0,sizeof(res.a));res.a[0]=1;
        for ( ;n;n>>=1,p=p*p ) if ( n&1 ) res=res*p;
        return res;
    }
}A,B;
signed main()
{
    scanf("%d%d%d",&n,&m,&p);
    flag[1]=true;
    for ( int i=2;i<=m;i++ )
    {
        if ( !flag[i] ) pr[++tot]=i;
        for ( int j=1;j<=tot and pr[j]*i<=m;j++ )
        {
            flag[i*pr[j]]=true;
            if ( !(j%i) ) break;
        }
    }
    for ( int i=1;i<=m;i++ ) A.a[i%p]++,B.a[i%p]+=flag[i];
    for ( int i=0;i<p;i++ ) A.a[i]%=mod,B.a[i]%=mod;
    printf("%d\n",((A^n)-(B^n)).a[0]);
}

原文地址:https://www.cnblogs.com/RenSheYu/p/11327244.html

时间: 2024-10-22 03:53:42

DTOJ #3160. 序列计数(count)的相关文章

序列计数(count)

Portal -->broken qwq Description ?? ?给你一个长度为\(n\)的序列,序列中的每个数都是不超过\(m\)的正整数,求满足以下两个条件的序列数量: 1.序列中至少有一个质数 2.序列中\(n\)个数之和为\(p\)的倍数 ?? ?数据范围:\(1<=n<=10^9,1<=m<=2*10^7,1<=p<=100\) Solution ?? ?我的妈呀真实智力康复..为什么连最基础的矩乘优化都忘了== ?? ?记\(f[i][j]\)

[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<

AC日记——「SDOI2017」序列计数 LibreOJ 2002

「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 20170408 #define ll long long struct MatrixType { int n,m; ll ai[105][105]; void mem(int n_,int m_) { n=n_,m=m_; for(int i=0;i<=n;i++) for(int v=0;v<=m;v++

LibreOJ #2002. 「SDOI2017」序列计数

二次联通门 : LibreOJ #2002. 「SDOI2017」序列计数 /* LibreOJ #2002. 「SDOI2017」序列计数 线性筛 + 矩阵优化dp 先构造出全部情况的矩阵 用矩阵快速幂计算答案 再构造出全不是质数的矩阵 计算出答案 前一个答案减后一个答案即可 */ #include <cstdio> #include <iostream> #include <cstring> const int BUF = 12312312; char Buf[BU

【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

P3702 [SDOI2017]序列计数

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

luogu3702-[SDOI2017]序列计数

Description Alice想要得到一个长度为nn的序列,序列中的数都是不超过mm的正整数,而且这nn个数的和是pp的倍数. Alice还希望,这nn个数中,至少有一个数是质数. Alice想知道,有多少个序列满足她的要求. 输入输出格式 输入格式: 一行三个数,n,m,p. 输出格式: 一行一个数,满足Alice的要求的序列数量,答案对20170408取模. 输入输出样例 输入样例#1: 3 5 3 输出样例#1: 33 说明 对20%的数据,1≤n,m≤100 对50%的数据,1≤m≤

[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

STL_算法_元素计数(count、count_if)

C++ Primer 学习中... 简单记录下我的学习过程 (代码为主) count . count_if #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<set> #include<algorithm> using namespace std; /*********************** count count_if