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 Output

33


求至少有一个质数的方案可以用总方案减去不含质数的方案。

先把1~m的质数筛出来,观察p特别小,考虑每个数%p的值对答案的贡献。

设F[i][j]表示从%p=i到%p=j的方案数,这个矩阵乘1次相当于向序列里多塞了个数,于是这道题变成了矩阵乘法。

然后发现f[i][j]=f[i+1][j+1],因此只需要对每个1~m中的i,f[0][i%p]++即可,剩下的可以通过平移得到。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
ll mod=20170408;
int n,m,p,prime[7000050],cnt;
bool vis[20000050];
struct Mat {
    ll v[105][105];
    Mat() {memset(v,0,sizeof(v));}
    Mat operator*(const Mat a) const {
        Mat ans;
        int i,j,k;
        for(i=1;i<=p;i++)
            for(j=1;j<=p;j++)
                for(k=1;k<=p;k++)
                    (ans.v[i][j]+=v[i][k]*a.v[k][j])%=mod;
        return ans;
    }
}A,B;
Mat pow(Mat x,int y) {
    Mat I;
    int i;
    for(i=1;i<=p;i++) I.v[i][i]=1;
    while(y) {
        if(y&1) I=I*x;
        x=x*x;
        y>>=1;
    }
    return I;
}
void init() {
    register int i,j;
    vis[1]=1;
    for(i=2;i<=m;i++) {
        if(!vis[i]) {
            prime[++cnt]=i;
        }
        for(j=1;j<=cnt&&i*prime[j]<=m;j++) {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
int main() {
    int i,j;
    scanf("%d%d%d",&n,&m,&p);
    init();
    for(i=1;i<=m;i++) {
        A.v[p][(i-1)%p+1]++;
        if(vis[i]) B.v[p][(i-1)%p+1]++;
    }
    for(i=p-1;i;i--) {
        for(j=1;j<=p;j++) {
            A.v[i][j]=A.v[i+1][j%p+1];
            B.v[i][j]=B.v[i+1][j%p+1];
        }
    }
    printf("%lld\n",(pow(A,n).v[p][p]-pow(B,n).v[p][p]+mod)%mod);
}

原文地址:https://www.cnblogs.com/suika/p/8832021.html

时间: 2024-11-05 16:10:43

BZOJ_4818_[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]序列计数 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

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,

[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

【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

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

B20J_1297_[SCOI2009]迷路_矩阵乘法

题意:有向图 N 个节点,从节点 0 出发,必须恰好在 T 时刻到达节点 N-1.总共有多少种不同的路径? 2 <= N <= 10 : 1 <= T <= 1000000000   边权范围[1,9]. 分析:首先看题目数据性质,N很小,即使是完全图边数也不会超过100.因此我们可以利用矩阵乘法优化. 如何优化:1.我们发现,当边权为1时每走一步就相当于乘上一次图的邻接矩阵.可以用矩阵快速幂O(N^3*logT)快速解决: 2.如果边权不为1我们可以运用拆点的技巧. 代码 值得注

BZOJ 4818 SDOI2017 序列计数

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