zoukankan      html  css  js  c++  java
  • [BZOJ4818][SDOI2017]序列计数(动规+快速幂)

    4818: [Sdoi2017]序列计数

    Time Limit: 30 Sec  Memory Limit: 128 MB
    Submit: 972  Solved: 581
    [Submit][Status][Discuss]

    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

    HINT

    Source

    [Submit][Status][Discuss]

    水题,同[六省联考2017 组合数问题]。

    首先套用上题做法,我想到的是f[i][j][0/1]表示前i个数总和%p=j的(不必须/必须有质数)的方案数,那么有转移状态:

    f[i+j][(x+y)%p][0]+=f[i][x][0]*f[j][y][0]

    f[i+j][(x+y)%p][1]+=f[i][x][1]*f[j][y][0]+f[i][x][0]*f[j][y][1]-f[i][x][1]*f[j][y][1]

    这个可能是可以矩乘优化的但由于0和1互相转移所以比较麻烦。

    那么我们考虑答案就是总方案数-不包含质数的方案数。

    f[i][j]表示前i个数总和%p=j的方案数,g[i][j]表示前i个数(不包含质数)总和%p=j的方案数,这两个转移互不影响。

    这样我们线性筛出m以内的质数,问题就完全变成上面那道题了。

    $O(m+p^2log n)$复杂度竟然能过?光一个线性筛搞不好就超了吧。。常数有点玄学啊,还是要敢写。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 using namespace std;
     5 
     6 const int N=210,M=20000100,mod=20170408;
     7 bool b[M];
     8 int n,m,p,tot,c[N],f[N],g[N],F[N],G[N],pr[5000100];
     9 
    10 void pre(){
    11     for (int i=2; i<=m; i++){
    12         if (!b[i]) pr[++tot]=i;
    13         for (int j=1; j<=tot && pr[j]*i<=m; j++){
    14             int t=pr[j]*i; b[t]=1;
    15             if (i%pr[j]==0) break;
    16         }
    17     }
    18 }
    19 
    20 void mul(int a[],int b[]){
    21     rep(i,0,p) c[i]=0;
    22     for (int i=0; i<p; i++) for (int j=0; j<p; j++) c[(i+j)%p]=(c[(i+j)%p]+1ll*a[i]*b[j])%mod;
    23     rep(i,0,p) a[i]=c[i];
    24 }
    25 
    26 int main(){
    27     freopen("count.in","r",stdin);
    28     freopen("count.out","w",stdout);
    29     scanf("%d%d%d",&n,&m,&p); pre();
    30     F[0]=G[0]=1; b[1]=1;
    31     rep(i,1,m) f[i%p]=(f[i%p]+1)%mod,g[i%p]=(g[i%p]+b[i])%mod;
    32     for (; n; mul(f,f),mul(g,g),n>>=1)
    33         if (n & 1) mul(F,f),mul(G,g);
    34     printf("%d
    ",(F[0]-G[0]+mod)%mod);
    35     return 0;
    36 }
  • 相关阅读:
    android bitmap 防止 内存溢出
    析android应用增量升级(差分升级)
    android 数据库查询中使用索引-大幅提高数据库操作速度
    android 插件框架
    android悬浮view-FloatingView
    android 消息分发框架 otto
    修改了USER_AGENT还是不能抓取到数据怎么办?
    找不到指定文件scrapy,在pycharm中运行程序出现错误
    scrapy抓取豆瓣网信息时报错提醒403[scrapy.spidermiddlewares.httperror] INFO
    slidetoshutdown电脑滑动关机命令失效了怎么办?
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8721473.html
Copyright © 2011-2022 走看看