Codeforces-1096G:Lucky Tickets(NTT)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/85346137

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 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 digits is equal to the sum of remaining n 2 \frac n2 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) — 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) — 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] 为前 n 2 \frac n2 个位置构成数位和为 i i 的方案数,那么答案就是 A [ i ] 2 \sum A[i]^2
那么求A数组就可以用NTT来求,由于是 n 2 \frac n2 次方的多项式,还需要快速幂。

#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;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/85346137
NTT