G. Lucky Tickets
time limit per test 5 seconds
memory limit per test 256 megabytes
inputstandard input
outputstandard output
All bus tickets in Berland have their numbers. A number consists of n digits (n is even). Only k decimal digits d 1 , d 2 , … , d k d_1,d_2,…,d_k 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 \frac n2 2n digits is equal to the sum of remaining n 2 \frac n2 2n 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
(
2
≤
n
≤
2
⋅
1
0
5
,
1
≤
k
≤
10
)
(2≤n≤2⋅10^5,1≤k≤10)
(2≤n≤2⋅105,1≤k≤10) — 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 d 1 , d 2 , … , d k ( 0 ≤ d i ≤ 9 ) d_1,d_2,…,d_k (0≤d_i≤9) d1,d2,…,dk(0≤di≤9) — 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
4 2
1 8
output
6
input
20 1
6
output
1
input
10 5
6 1 4 0 3
output
569725
input
1000 7
5 4 0 1 8 3 2
output
460571165
思路:假设
A
[
i
]
A[i]
A[i]为前
n
2
\frac n2
2n个位置构成数位和为
i
i
i的方案数,那么答案就是
∑
A
[
i
]
2
\sum A[i]^2
∑A[i]2。
那么求A数组就可以用NTT来求,由于是
n
2
\frac n2
2n次方的多项式,还需要快速幂。
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int MOD=998244353;
const int G=3;
typedef long long ll;
ll POW(ll x,ll n)
{
ll res=1;
while(n)
{
if(n&1)res=res*x%MOD;
x=x*x%MOD;
n/=2;
}
return res;
}
int rev(int x,int len)
{
int ret=0;
for(int i=0;(1<<i)<len;i++)
{
ret<<=1;
if(x&(1<<i))ret|=1;
}
return ret;
}
void NTT(ll *p,ll len,int tag)
{
for(int i=0;i<len;i++)
{
ll x=rev(i,len);
if(i<x)swap(p[i],p[x]);
}
for(int i=1;i<len;i<<=1)
{
ll wn=POW(G,(MOD-1)/(2*i)); //G为原根
if(tag==-1)wn=POW(wn,MOD-2);
for(int j=0;j<len;j+=i*2)
{
ll w=1;
for(int k=0;k<i;k++)
{
ll x=p[j+k];
ll y=w*p[j+k+i]%MOD;
p[j+k]=(x+y)%MOD;
p[j+k+i]=(x-y+MOD)%MOD;
w=w*wn%MOD;
}
}
}
if(tag==-1)for(int i=0,x=POW(len,MOD-2);i<len;i++)p[i]=p[i]*x%MOD;
}
ll A[10*MAX];
int main()
{
int n,k;
cin>>n>>k;
for(int i=0;i<k;i++)
{
int x;
scanf("%d",&x);
A[x]=1;
}
int len=1;
while(len<5*n)len*=2;
NTT(A,len,1);
for(int i=0;i<len;i++)A[i]=POW(A[i],n/2);
NTT(A,len,-1);
ll ans=0;
for(int i=0;i<len;i++)(ans+=A[i]*A[i]%MOD)%=MOD;
cout<<ans<<endl;
return 0;
}