codevs 5964 [SDOI2017]序列计数

 [题解]

官方题解就两句话。

写了三个版本的不同分值代码。看代码吧。

前导1

//f[i][j][1/0]表示长为i,sum mod p=j,是否已经选了质数的方案数
#include<cstdio>
using namespace std;
const int mod=20170408;
const int N=1e6+1;
int tot,prime[N/3];bool check[N];
int n,m,f[2][N][2];int p;
void pre(){
    n=1e6;check[0]=check[1]=1;
    for(int i=2;i<=n;i++){
        if(!check[i]) prime[++tot]=i;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            check[i*prime[j]]=1;
            if(!(i%prime[j])) break;
        }
    }
}
int main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    pre();
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=m;i++) f[1][i%p][!check[i]]++;
    for(int i=1,val;i<n;i++){
        for(int j=0;j<p;j++){
            for(int k=1;k<=m;k++){
                val=(j+k)%p;
                if(!check[k]){
                    f[i+1&1][val][1]=(f[i+1&1][val][1]+f[i&1][j][0]+f[i&1][j][1])%mod;
                }
                else{
                    f[i+1&1][val][0]=(f[i+1&1][val][0]+f[i&1][j][0])%mod,
                    f[i+1&1][val][1]=(f[i+1&1][val][1]+f[i&1][j][1])%mod;
                }
            }
        }
        for(int j=0;j<p;j++){
            f[i&1][j][0]=0;
            f[i&1][j][1]=0;
        }
    }
    printf("%d",f[n&1][0][1]);
    return 0;
}

前导2

#include<cstdio>
using namespace std;
const int mod=20170408;
const int N=1e6+1;
int tot,prime[N/3];bool check[N];
int n,m,p;
int f[2][N];
int g[2][N];
int sz[N];
void pre(){
    n=1e6;check[0]=check[1]=1;
    for(int i=2;i<=n;i++){
        if(!check[i]) prime[++tot]=i;
        for(int j=1;j<=tot&&i*prime[j]<=n;j++){
            check[i*prime[j]]=1;
            if(!(i%prime[j])) break;
        }
    }
}
int main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    pre();
    scanf("%d%d%d",&n,&m,&p);
    //全集
    for(int k=1;k<=p;k++) sz[k]=m/p+(m%p>=k);sz[0]=sz[p];
    for(int i=0;i<p;i++) f[1][i]=sz[i];
    for(int i=1,val;i<n;i++){
        for(int j=0;j<p;j++){
            for(int k=0;k<p;k++){
                val=(j+k)%p;
                f[i+1&1][val]=(f[i+1&1][val]+sz[k]*f[i&1][j])%mod;
            }
        }
        for(int j=0;j<p;j++) f[i&1][j]=0;
    }
    //不包含素数
    for(int i=1;i<=tot&&prime[i]<=m;i++) sz[prime[i]%p]--;
    for(int i=0;i<p;i++) g[1][i]=sz[i];
    for(int i=1,val;i<n;i++){
        for(int j=0;j<p;j++){
            for(int k=0;k<p;k++){
                val=(j+k)%p;
                g[i+1&1][val]=(g[i+1&1][val]+sz[k]*g[i&1][j])%mod;
            }
        }
        for(int j=0;j<p;j++) g[i&1][j]=0;
    }
    printf("%d",f[n&1][0]-g[n&1][0]);
    return 0;
}

AC代码

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int mod=20170408;
const int N=101;
const int M=2e7+5;
int tot,prime[M/3];bool check[M];
int n,m,p;
int sz[N];
struct matrix{
    ll s[N];//降低常数
    matrix(){
        memset(s,0,sizeof s);
    }
}A,B;
matrix operator *(const matrix &a,const matrix &b){
    matrix c;
    for(int i=0;i<p;i++){
//        c.s[i]=0;
        for(int k=0;k<p;k++){
            c.s[i]+=a.s[(i-k+p)%p]*b.s[k];
            c.s[i]%=mod;
        }
    }
    return c;
}
ll fpow(matrix a,ll p){
    matrix res;
//    for(int i=0;i<p;i++) res.s[i]=0;
    res.s[0]=1;
    for(;p;p>>=1,a=a*a) if(p&1) res=res*a;
    return res.s[0];
}
void pre(){
    check[0]=check[1]=1;
    for(int i=2;i<=m;i++){
        if(!check[i]) prime[++tot]=i;
        for(int j=1;j<=tot&&i*prime[j]<=m;j++){
            check[i*prime[j]]=1;
            if(!(i%prime[j])) break;
        }
    }
}
int main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    scanf("%d%d%d",&n,&m,&p);
    pre();
    for(int k=1;k<=p;k++) sz[k]=m/p+(m%p>=k);sz[0]=sz[p];
    for(int i=0;i<p;i++) A.s[i]=sz[i];
    for(int i=1;i<=tot&&prime[i]<=m;i++) sz[prime[i]%p]--;
    for(int i=0;i<p;i++) B.s[i]=sz[i];
    ll ans=(fpow(A,n)-fpow(B,n))%mod;if(ans<0) ans+=mod;
    printf("%lld",ans);
    return 0;
} 
时间: 2024-11-07 06:34:46

codevs 5964 [SDOI2017]序列计数的相关文章

【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

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

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]$表示满足没有一个数是质数的情况下长度为$

[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]序列计数 矩阵乘法

原文地址: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_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

BZOJ 4818 SDOI2017 序列计数

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