设\(f[i][j]\)表示填了\(i\)个数,数位和为\(j\)的方案数

于是方程为:
\[f[i][j]=\sum_{k=0}^9 f[i-1][j-k]*[CanUse[k]==1]\]

其中\(CanUse[i]\)表示是否可用\(i\)这个数字

最终答案为:
\[\sum_{i=0}^{9*(n/2)}f[n/2][j]\]

直接转移肯定\(T\)飞,需要一些优化。于是我们观察到这个式子是卷积形式的式子,直接上\(NTT\)板子+快速幂即可

\(P.S.\)一些优化

  1. 可以把每个\(pow(g,(mod-1)/i)\)和\(pow(g,-(mod-1)/i)\)预处理出来,\(NTT\)过程中直接调用

  2. 快速幂前可以直接把系数表示化为点值表示,快速幂时直接乘,快速幂后再换回去系数表示

所以时间复杂度为\(0(9*(n/2)log_29*(n/2))\)

代码:

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353ll
#define N 1048580
using namespace std;
ll G[N],F[N],tmp[N],tot[N],invG[N],inv,ans=0;
const ll g=3;
int rev[N],len,x;
void NTT(ll *a,int n,int f){
    int i,j,k;
    for(i=0;i<n;++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(i=2;i<=n;i<<=1){
        ll omega;
        int m=i>>1;
        (f==1)?omega=G[i]:omega=invG[i];
        for(j=0;j<n;j+=i){
            ll p=1;
            for(k=j;k<j+m;++k,(p*=omega)%=mod){
                ll u=a[k],v=p*a[k+m]%mod;
                a[k]=(u+v)%mod,a[k+m]=(u-v+mod)%mod;
            }
        }
    }
    if(f==-1) for(i=0;i<n;++i) (a[i]*=inv)%=mod;
}
ll ksm(ll x,int y){
    ll ans=1;
    while(y){
        if(y&1) (ans*=x)%=mod;
        (x*=x)%=mod;
        y>>=1;
    }
    return ans;
}
void init(int n){
    int i;
    for(len=1,x=0;len<=n;len<<=1,++x);
    for(i=0;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(x-1));
    G[len]=ksm(g,(mod-1)/len),invG[len]=ksm(g,mod-1-(mod-1)/len);
    for(i=(len>>1);i>=2;i>>=1){
        G[i]=G[i<<1]*G[i<<1]%mod;
        invG[i]=invG[i<<1]*invG[i<<1]%mod;
    }
}
void mul(ll *a,ll *b){
    for(int i=0;i<len;++i) a[i]=a[i]*b[i]%mod;
}
int main(){
    int n,d,i;
    scanf("%d%d",&n,&d);n/=2;
    for(i=1;i<=d;++i) scanf("%d",&x),F[x]=1;
    init(9*n);
    tot[0]=1;inv=ksm(1ll*len,mod-2);
    NTT(F,len,1),NTT(tot,len,1);
    x=n;
    while(x){
        if(x&1) mul(tot,F);
        x>>=1;
        if(x) mul(F,F);
    }
    NTT(tot,len,-1);
    for(i=0;i<=9*n;++i) (ans+=tot[i]*tot[i]%mod)%=mod;
    cout<<ans;
}

Codeforces1096G Lucky Tickets(NTT优化dp)的更多相关文章

  1. ZOJ 3874 Permutation Graph (分治NTT优化DP)

    题面:vjudge传送门 ZOJ传送门 题目大意:给你一个排列,如果两个数构成了逆序对,就在他们之间连一条无向边,这样很多数会构成一个联通块.现在给出联通块内点的编号,求所有可能的排列数 推来推去容易 ...

  2. POJ-2346 Lucky tickets(线性DP)

    Lucky tickets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3298 Accepted: 2174 Descrip ...

  3. 4.13 省选模拟赛 树 树形dp 卷积 NTT优化dp.

    考试的时候 看到概率 看到期望我就怂 推了一波矩阵树推自闭了 发现 边权点权的什么也不是. 想到了树形dp 维护所有边的断开情况 然后发现数联通块的和再k次方过于困难. 这个时候 应该仔细观察一下 和 ...

  4. HDU 5279 YJC plays Minecraft (分治NTT优化DP)

    题目传送门 题目大意:有$n$个小岛,每个小岛上有$a_{i}$个城市,同一个小岛上的城市互相连接形成一个完全图,第$i$个小岛的第$a_{i}$个城市和第$i+1$个小岛的第$1$个城市连接,特别地 ...

  5. HDU 5322 Hope (分治NTT优化DP)

    题面传送门 题目大意: 假设现在有一个排列,每个数和在它右面第一个比它大的数连一条无向边,会形成很多联通块. 定义一个联通块的权值为:联通块内元素数量的平方. 定义一个排列的权值为:每个联通块的权值之 ...

  6. Codeforces - 1096G - Lucky Tickets - NTT

    https://codeforc.es/contest/1096/problem/G 把数组分成前后两半,那么前半部分的各个值的表示方案的平方的和就是答案. 这些数组好像可以dp出来. 一开始设dp[ ...

  7. codeforces1096G Lucky Tickets

    题目链接:https://codeforces.com/problemset/problem/1096/G 大意:给出\(k\)个数码\(d_1,d_2,\cdots,d_k\),构造一个由这\(k\ ...

  8. Gym 100418J Lucky tickets(数位dp)

    题意:给定一个n.求区间[1, n]之间的全部的a的个数.a满足: a能整除  把a表示自身二进制以后1的个数 思路:题意非常绕.... 数位dp,对于全部可能的1的个数我们都dfs一次 对于某一个可 ...

  9. Codeforces Gym 100418J Lucky tickets 数位DP

    Lucky ticketsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view ...

随机推荐

  1. composer 自动加载一 通过file加载

    github地址 https://github.com/brady-wang/composer composer init 可以生成一个composer.json文件 { "name&quo ...

  2. Linux中各个目录作用

    对于linux新手来说,最感到迷惑的问题之一就是文件都存在哪里呢?特别是对于那些从windows转过来的新手来说,linux的目录结构看起来有些奇怪哦.比如没有C盘,没有分盘符,一大堆不知道用途的文件 ...

  3. Eclipse的智能提示的设置

    智能提示修改方式是: Windows——>Preferences——>Java-->Editor-->Content Asist,在Auto activation trigge ...

  4. flutter-StatelessWidget与StatefulWidget

    StatelessWidget和StatefulWidget是flutter的基础组件,日常开发中自定义Widget都是选择继承这两者之一. 两者的区别在于状态的改变,StatelessWidget面 ...

  5. python爬虫之scrapy文件下载

    我们在写普通脚本的时候,从一个网站拿到一个文件的下载url,然后下载,直接将数据写入文件或者保存下来,但是这个需要我们自己一点一点的写出来,而且反复利用率并不高,为了不重复造轮子,scrapy提供很流 ...

  6. python学习笔记(4)-基本数据类型-数字类型及操作

    大学mooc 北京理工大学 python语言程序设计课程学习笔记 一.整数类型 可正可负,没有取值范围的限制(这个与c不同,c要考虑数据类型的存储空间).如pow(x,y),计算x的y次方,pow(2 ...

  7. 老男孩python学习自修第十四天【序列化和json】

    序列化是使用二进制的方式加密列表,字典或集合,反序列化是解密的过程:序列化开启了两个独立进程进行数据交互的通路 使用pickle进行序列化和反序列化 例如: pickle_test.py #!/usr ...

  8. 初识Anrdiod SDK

    概念 SDK:(software development kit)软件开发工具包.被软件开发工程师用于为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件的开发工具的集合. 因此,Android ...

  9. 深度学习+CRF解决NER问题

    参考https://github.com/shiyybua/NER 1.开发环境:python3.5+tensorflow1.5+pycharm 2.从https://github.com/shiyy ...

  10. vue-cli: render:h => h(App)是什么意思

    import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: ...