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 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 digits is equal to the sum of remaining 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
— 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 — 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数组就可以用NTT来求,由于是
次方的多项式,还需要快速幂。
#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;
}