Live2d Test Env

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

All bus tickets in Berland have their numbers. A number consists of n digits (n is even). Only k decimal digits d1,d2,,dk can be used to form ticket numbers. If 0 is among these digits, then numbers may have leading zeroes. For example, if n=4 and only digits 0 and 4 can be used, then 0000, 4004, 4440 are valid ticket numbers, and 0002, 00, 44443

are not.

A ticket is lucky if the sum of first n/2

digits is equal to the sum of remaining n/2

digits.

Calculate the number of different lucky tickets in Berland. Since the answer may be big, print it modulo 998244353

.

Input

The first line contains two integers n

and k (2n2105,1k10) — the number of digits in each ticket number, and the number of different decimal digits that may be used. n

is even.

The second line contains a sequence of pairwise distinct integers d1,d2,,dk

(0di9)

— the digits that may be used in ticket numbers. The digits are given in arbitrary order.

Output

Print the number of lucky ticket numbers, taken modulo 998244353

.

Examples
Input
Copy
4 2
1 8
Output
Copy
6
Input
Copy
20 1
6
Output
Copy
1
Input
Copy
10 5
6 1 4 0 3
Output
Copy
569725
Input
Copy
1000 7
5 4 0 1 8 3 2
Output
Copy
460571165
Note

In the first example there are 6

lucky ticket numbers: 1111, 1818, 1881, 8118, 8181 and 8888

.

There is only one ticket number in the second example, it consists of 20

digits 6. This ticket number is lucky, so the answer is 1.

 

题意:给定你K种数可以选,问你有多少排列,使得前半部分的和等于后半部分的和。

思路:我们枚举“和”的大小,令A[i]表示长度为N/2时和为i的方案数,那么答案就是所有的A[i]*A[i];

怎么就Ai呢,就是一个多项式(P0.X0+P1*X1+...*P9*X9)^(N/2);p是0或者1;

多项式的N次,我们可以用快速幂+FFT来加速,这里要取模,写的NTT。然后就是可以直接一次DFT+快速幂+IDFT。

(之前纠结过为什么可以一次DFT就搞定了,而不是logN次,现在看来是对的,正确性我还需要学习一下。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
#define ll long long
const int G=3;
const int maxn=2148576;
const int Mod=998244353;
int mod,n,k,rev[maxn],lim,ilim,s,wn[maxn+1];
std::vector<int> v;
inline int pow(int x, int y) {
    int ans=1;
    for(;y;y>>=1,x=(ll)x*x%mod)
      if(y&1) ans=(ll)ans*x%mod;
    return ans;
}
inline int& up(int& x, int y) { if ((x+=y)>=mod) x-=mod; return x; }
inline void NTT(int* A, int typ) {
    rep(i,0,lim-1) if (i<rev[i]) swap(A[i], A[rev[i]]);
    for (int i=1;i<lim;i+=i) {
        const int t=lim/i/2;
        for (int j=0;j<lim;j+=i+i) {
            for (int k=0;k<i; k++) {
                int w=typ?wn[t*k]:wn[lim-t*k];
                int x=A[k+j],y=(ll)w*A[k+j+i]%mod;
                up(A[k+j],y),up(A[k+j+i]=x,mod-y);
            }
        }
    }
    if (!typ) rep(i,0,lim-1) A[i]=(ll)ilim*A[i]%mod;
}
inline void init(int len,int tmod) {
    mod=tmod; lim=1; s=-1;
    while(lim<len) lim+=lim,s++;  ilim=pow(lim,mod-2);
    rep(i,0,lim-1) rev[i]=rev[i>>1]>>1|(i&1)<<s;
    int w=pow(G,(mod-1)/len);
    wn[0]=1;
    rep(i,1,lim) wn[i]=(ll)(wn[i-1])*w%mod;
}
int A[maxn];
int main() {
    scanf("%d%d",&k,&n); k/=2;
    int x,ans=0; rep(i,1,n) scanf("%d",&x), A[x]=B[x]=1;
    init(2097152, 998244353);
    NTT(A, 1);
    rep(i,0,lim-1) A[i]=pow(A[i],k);
    NTT(A, 0);
    rep(i,0,2000000) (ans+=(ll)A[i]*A[i]%Mod)%=Mod;
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-12-29 10:58  nimphy  阅读(750)  评论(0编辑  收藏  举报