@description@

已知一个数(允许前导零)有 n 位(n 为偶数),并知道组成这个数的数字集合(并不一定要把集合内的数用完)。求有多少种可能,使得这个数前半部分的数位和等于后半部分的数位和。

模 998244353。

input

第一行两个整数:n k。表示这个数的位数以及组成这个数的数字集合大小。2 <= n <= 2*10^5,1 <= k <= 10。

第二行 k 个两两不同的整数 d1,d2,...,dk,表示组成这个数的数字集合。0 <= di <= 9。

output

输出可能数,模 998244353。

sample input

4 2

1 8

sample output

6

sample explain

6 种可能分别是:1111,1818,8118,1881,8181,8888。

@solution@

模数暗示 NTT。

如果长度为 n/2,数位和为 s 的数有 k 种,则它对答案的贡献为 \(k^2\)。

问题等价于求,长度为 n/2,数位和为 0,1,2,... 的数有多少种。

我们于是可以 dp。定义状态 \(dp[i][j]\) 表示长度为 i 的数,数位和为 j 的方案数。

定义 \(f\),使得 \(f[d[i]]=1(1\le i \le k)\)。可以得到状态转移方程:

\[dp[i][j] = \sum_{k=0}^{9}dp[i-1][j-k]*f[k]
\]

嗯好的这是一个卷积形式的 dp,我们可以用 NTT 来优化。

可以得到 \(dp[\frac{n}{2}][j] = f^{\frac{n}{2}}[j]\)。

转换成点值形式后直接快速幂再转换回来。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
const int G = 3;
const int MOD = 998244353;
const int MAXN = 200000*9*2;
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 ) ret = 1LL*ret*b%MOD;
b = 1LL*b*b%MOD;
p >>= 1;
}
return ret;
}
void ntt(int A[], int n, int type) {
for(int i=0,j=0;i<n;i++) {
if( i < j ) swap(A[i], A[j]);
for(int l=(n>>1);(j^=l)<l;l>>=1);
}
for(int s=2;s<=n;s<<=1) {
int t = (s >> 1);
int u = (type == 1) ? (pow_mod(G, (MOD-1)/s)) : (pow_mod(G, (MOD-1)-(MOD-1)/s));
for(int i=0;i<n;i+=s) {
for(int p=1,j=0;j<t;j++,p=1LL*p*u%MOD) {
int x = A[i+j], y = 1LL*A[i+j+t]*p%MOD;
A[i+j] = (x + y)%MOD, A[i+j+t] = (x + MOD - y)%MOD;
}
}
}
if( type == -1 ) {
int inv = pow_mod(n, MOD-2);
for(int i=0;i<n;i++)
A[i] = 1LL*A[i]*inv%MOD;
}
}
int f[MAXN + 5];
int main() {
int n, k, d, mx = 0;
scanf("%d%d", &n, &k);
for(int i=1;i<=k;i++) {
scanf("%d", &d);
mx = max(mx, d);
f[d] = 1;
}
int len; for(len = 1;len <= ((n>>1)*mx);len<<=1);
ntt(f, len, 1);
for(int i=0;i<len;i++)
f[i] = pow_mod(f[i], (n>>1));
ntt(f, len, -1);
int ans = 0;
for(int i=0;i<len;i++)
ans = (ans + 1LL*f[i]*f[i]%MOD)%MOD;
printf("%d\n", ans);
}

@details@

连续做了几天多项式毒瘤算法,做一个卷积优化是真的轻松惬意。

我才不会说因为 mx 没有弄初值 RE 了让我懵逼了好久。

我怎么可能会因为傻逼错误做不出来傻逼题。

@codeforces - 1096G@ Lucky Tickets的更多相关文章

  1. 2019.01.26 codeforces 1096G. Lucky Tickets(生成函数)

    传送门 题意简述:现在有一些号码由000~999中的某些数字组成(会给出),号码总长度为nnn,问有多少个号码满足前n2\frac n22n​个数码的和等于后n2\frac n22n​个数码的和(保证 ...

  2. Codeforces 1096G. Lucky Tickets【生成函数】

    LINK 题目大意 很简单自己看 思路 考虑生成函数(为啥tags里面有一个dp啊) 显然,每一个指数上是否有系数是由数集中是否有这个数决定的 有的话就是1没有就是0 然后求出这个生成函数的\(\fr ...

  3. Codeforces - 1096G - Lucky Tickets - NTT

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

  4. Codeforces Gym 100418J Lucky tickets 数位DP

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

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

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

  6. CF1096. G. Lucky Tickets(快速幂NTT)

    All bus tickets in Berland have their numbers. A number consists of n digits (n is even). Only k dec ...

  7. DP+高精度 URAL 1036 Lucky Tickets

    题目传送门 /* 题意:转换就是求n位数字,总和为s/2的方案数 DP+高精度:状态转移方程:dp[cur^1][k+j] = dp[cur^1][k+j] + dp[cur][k]; 高精度直接拿J ...

  8. Ural 1036 Lucky Tickets

    Lucky Tickets Time Limit: 2000ms Memory Limit: 16384KB This problem will be judged on Ural. Original ...

  9. POJ 2346:Lucky tickets

    Lucky tickets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3247   Accepted: 2136 Des ...

随机推荐

  1. vim 的列操作

    删除列1.光标定位到要操作的地方.2.CTRL+v 进入“可视 块”模式,选取这一列操作多少行.3.d 删除. 插入列插入操作的话知识稍有区别.例如我们在每一行前都插入"() ": ...

  2. 直接在安装了redis的Linux机器上操作redis数据存储类型--对key的操作

    一.概述:   前几篇博客中,主要讲述的是与Redis数据类型相关的命令,如String.List.Set.Hashes和Sorted-Set.这些命令都具有一个共同点,即所有的操作都是针对与Key关 ...

  3. springMVC原理解析

    1:SpringMVC运行原理 2:工作流程 (1)客户端(浏览器)发送请求,直接请求到DispatcherServlet. (2)DispatcherServlet根据请求信息调用HandlerMa ...

  4. BIRT简介

    BIRT(Business Intelligence and Reporting Tools,商业智能和报告工具,曾被安讯公司中国分公司译作百灵)项目是一个开源软件项目,其为富客户端应用和Web应用程 ...

  5. php thrift TServerSocket实现端口复用

    <?php namespace Message\Controller; use Think\Controller; use Thrift\Exception\TException; use Th ...

  6. 蚁群算法MATLAB解VRP问题

    Excel  exp12_3_2.xls内容: ANT_VRP函数: function [R_best,L_best,L_ave,Shortest_Route,Shortest_Length]=ANT ...

  7. pillow模块

    pillow模块 用于操作图片的模块 安装 pip install pillow 生成验证码 from PIL import Image,ImageDraw,ImageFont from io imp ...

  8. UIImageView添加圆角

    最直接的方法就是使用如下属性设置: 1 2 3 imgView.layer.cornerRadius = 10; // 这一行代码是很消耗性能的 imgView.clipsToBounds = YES ...

  9. VLSM(可变长子网掩码)

    http://blog.sina.com.cn/s/blog_635e1a9e0100yk51.html(转载) VLSM的介绍: VLSM(VLSM(Variable Length Subnetwo ...

  10. 【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup

    [链接]h在这里写链接 [题意]     k是最高级别的分数,最高界别的分数最多只能有x个.     1<=k<=m;     和k相邻的点的分数只能小于k;     n个点的树,问你每个 ...