HDU 6340 Problem I. Delightful Formulas(莫比乌斯反演+数论+FFT)

201 篇文章 10 订阅
28 篇文章 0 订阅

Description

给出 n,K n , K ,令 si=jijK s i = ∑ j ≤ i j K ,求 1insi[gcd(i,n)=1] ∑ 1 ≤ i ≤ n s i [ g c d ( i , n ) = 1 ]

Input

第一行一整数 T T 表示用例组数,每组用例首先输入一整数K,之后输入一整数 m m 表示n的素因子数量,最后输入 m m 对整数pi,ai表示 n=i=1npaii n = ∏ i = 1 n p i a i

(K105,K106,m20,pi,ai109,pi<pi+1) ( K ≤ 10 5 , ∑ K ≤ 10 6 , m ≤ 20 , p i , a i ≤ 10 9 , p i < p i + 1 )

Output

输出答案,结果模 109+7 10 9 + 7

Sample Input

2
1
2
2 1
3 1
233
1
23333 1

Sample Output

16
32727388

Solution

对所求表达式反演有

ans===i=1n[(i,n)=1]j=1ijKi=1nd|(i,n)μ(d)S(i,K)d|nμ(d)i=1ndS(id,K) a n s = ∑ i = 1 n [ ( i , n ) = 1 ] ∑ j = 1 i j K = ∑ i = 1 n ∑ d | ( i , n ) μ ( d ) S ( i , K ) = ∑ d | n μ ( d ) ∑ i = 1 n d S ( i d , K )

其中 S(n,k)=i=1nik=1k+1i=1k+1Cik+1Bk+1i(n+1)i S ( n , k ) = ∑ i = 1 n i k = 1 k + 1 ∑ i = 1 k + 1 C k + 1 i B k + 1 − i ( n + 1 ) i B0=1,i=0nCin+1Bi=0 B 0 = 1 , ∑ i = 0 n C n + 1 i B i = 0 为伯努利序列

预处理伯努利序列,由于 i=0nCin+1Bi=(n+1)!i=0nBii!1(n+1i)!=0 ∑ i = 0 n C n + 1 i B i = ( n + 1 ) ! ∑ i = 0 n B i i ! 1 ( n + 1 − i ) ! = 0 ,而 B0=1 B 0 = 1 ,故多项式 f(x)=Bii!xi f ( x ) = ∑ B i i ! x i 即为多项式 g(x)=(n+1i)!xi g ( x ) = ∑ ( n + 1 − i ) ! x i 的逆,用多项式求逆即可 O(Klog2K) O ( K l o g 2 K ) 得到伯努利序列

考虑到 S(n,k) S ( n , k ) 为一个关于 n n k+1阶多项式,设 S(n,k)=j=0k+1ak,jnj S ( n , k ) = ∑ j = 0 k + 1 a k , j n j ,先求 ak,j a k , j ,由于

S(n,k)====1k+1i=1k+1Cik+1Bk+1i(n+1)i1k+1i=0k+1Cik+1Bk+1i(n+1)i1k+1Bk+11k+1i=0k+1Cik+1Bk+1ij=0iCjinj1k+1Bk+1j=0k+1nji=jk+1Cik+1CjiBk+1i1k+1Bk+1 S ( n , k ) = 1 k + 1 ∑ i = 1 k + 1 C k + 1 i B k + 1 − i ( n + 1 ) i = 1 k + 1 ∑ i = 0 k + 1 C k + 1 i B k + 1 − i ( n + 1 ) i − 1 k + 1 B k + 1 = 1 k + 1 ∑ i = 0 k + 1 C k + 1 i B k + 1 − i ∑ j = 0 i C i j n j − 1 k + 1 B k + 1 = ∑ j = 0 k + 1 n j ∑ i = j k + 1 C k + 1 i C i j B k + 1 − i − 1 k + 1 B k + 1

显然有 ak,0=0 a k , 0 = 0 ,当 j1 j ≥ 1 时有
ak,j=======1k+1i=jk+1Cik+1CjiBk+1i1k+1i=0k+1jCik+1Cjk+1iBi1k+1i=0k+1j(k+1)!(k+1i)!i!(k+1i)!j!(k+1ij)!Bi1k+1i=0k+1j(k+1)!(k+1j)!i!(k+1j)!j!(k+1ij)!Bi1k+1i=0k+1jCik+1jCjk+1Bi1k+1Cjk+1(i=0kjCik+1jBi+Bk+1j)1k+1Cjk+1Bk+1jB0+B11k+11j<kj=kj=k+1 a k , j = 1 k + 1 ∑ i = j k + 1 C k + 1 i C i j B k + 1 − i = 1 k + 1 ∑ i = 0 k + 1 − j C k + 1 i C k + 1 − i j B i = 1 k + 1 ∑ i = 0 k + 1 − j ( k + 1 ) ! ( k + 1 − i ) ! i ! ( k + 1 − i ) ! j ! ( k + 1 − i − j ) ! B i = 1 k + 1 ∑ i = 0 k + 1 − j ( k + 1 ) ! ( k + 1 − j ) ! i ! ( k + 1 − j ) ! j ! ( k + 1 − i − j ) ! B i = 1 k + 1 ∑ i = 0 k + 1 − j C k + 1 − j i C k + 1 j B i = 1 k + 1 C k + 1 j ( ∑ i = 0 k − j C k + 1 − j i B i + B k + 1 − j ) = { 1 k + 1 C k + 1 j B k + 1 − j 1 ≤ j < k B 0 + B 1 j = k 1 k + 1 j = k + 1

注意到只要我们令 B1=B0+B1 B 1 = B 0 + B 1 ,那么有 ak,j=1k+1Cjk+1Bk+1j,j0,ak,0=0 a k , j = 1 k + 1 C k + 1 j B k + 1 − j , j ≥ 0 , a k , 0 = 0

得到 S(n,k) S ( n , k ) 后我们有

ans========d|nμ(d)i=1ndS(id,K)d|nμ(d)i=1ndj=0K+1aK,jijdjd|nμ(d)j=0K+1aK,jdji=1ndijd|nμ(d)j=0K+1aK,jdjk=0j+1aj,knkdkd|nμ(d)i=1K+1dij=0K+1k=0j+1[jk=i]aK,jaj,knkd|nμ(d)i=1K+1diFi+1i=1K+1Fi+1d|nμ(d)dii=1K+1Fi+1j=1m(1pij) a n s = ∑ d | n μ ( d ) ∑ i = 1 n d S ( i d , K ) = ∑ d | n μ ( d ) ∑ i = 1 n d ∑ j = 0 K + 1 a K , j i j d j = ∑ d | n μ ( d ) ∑ j = 0 K + 1 a K , j d j ∑ i = 1 n d i j = ∑ d | n μ ( d ) ∑ j = 0 K + 1 a K , j d j ∑ k = 0 j + 1 a j , k n k d − k = ∑ d | n μ ( d ) ∑ i = − 1 K + 1 d i ∑ j = 0 K + 1 ∑ k = 0 j + 1 [ j − k = i ] a K , j a j , k n k = ∑ d | n μ ( d ) ∑ i = − 1 K + 1 d i F i + 1 = ∑ i = − 1 K + 1 F i + 1 ∑ d | n μ ( d ) d i = ∑ i = − 1 K + 1 F i + 1 ∏ j = 1 m ( 1 − p j i )

其中 Fi=j=0K+1k=0j+1[jk=i1]aK,jaj,knk=j=0K+1aK,jaj,ji+1nji+1,0iK+2 F i = ∑ j = 0 K + 1 ∑ k = 0 j + 1 [ j − k = i − 1 ] a K , j a j , k n k = ∑ j = 0 K + 1 a K , j a j , j − i + 1 n j − i + 1 , 0 ≤ i ≤ K + 2

只要可以快速求出 F0,...,FK+2 F 0 , . . . , F K + 2 ,则可以 O(mK) O ( m K ) 的得到答案,最后考虑求 Fi F i ,由于 aK+1,0=0 a K + 1 , 0 = 0 ,故 FK+2=0 F K + 2 = 0

Fi=====j=0K+1aK,jaj,ji+1nji+1j=1K+1aK,jaj,ji+1nji+1j=0KaK,j+1aj+1,ji+2nji+2j=0K1K+1Cj+1K+1BKj1j+2Cij+2Binji+2K!Bii!j=0KBKj(Kj)!nji+2(ji+2)! F i = ∑ j = 0 K + 1 a K , j a j , j − i + 1 n j − i + 1 = ∑ j = 1 K + 1 a K , j a j , j − i + 1 n j − i + 1 = ∑ j = 0 K a K , j + 1 a j + 1 , j − i + 2 n j − i + 2 = ∑ j = 0 K 1 K + 1 C K + 1 j + 1 B K − j 1 j + 2 C j + 2 i B i n j − i + 2 = K ! B i i ! ∑ j = 0 K B K − j ( K − j ) ! n j − i + 2 ( j − i + 2 ) !

以上为一个卷积形式,用 FFT F F T 即可 O(KlogK) O ( K l o g K ) 求出 F0,...,FK+1 F 0 , . . . , F K + 1

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define maxn 100005
#define maxfft 262144+5
#define mod 998244353
int add(int x,int y)
{
    x+=y;
    if(x>=mod)x-=mod;
    return x;
}
int mul(int x,int y)
{
    ll z=1ll*x*y;
    return z-z/mod*mod;
}
int Pow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=mul(ans,a);
        a=mul(a,a);
        b>>=1;
    }
    return ans;
}
const double pi=acos(-1.0);
struct cp
{
    double a,b;
    cp operator +(const cp &o)const {return (cp){a+o.a,b+o.b};}
    cp operator -(const cp &o)const {return (cp){a-o.a,b-o.b};}
    cp operator *(const cp &o)const {return (cp){a*o.a-b*o.b,b*o.a+a*o.b};}
    cp operator *(const double &o)const {return (cp){a*o,b*o};}
    cp operator !() const{return (cp){a,-b};}
}w[maxfft];
int pos[maxfft];
void fft_init(int len)
{
    int j=0;
    while((1<<j)<len)j++;
    j--;
    for(int i=0;i<len;i++)
        pos[i]=pos[i>>1]>>1|((i&1)<<j);
}
void fft(cp *x,int len,int sta)
{
    for(int i=0;i<len;i++)
        if(i<pos[i])swap(x[i],x[pos[i]]);
    w[0]=(cp){1,0};
    for(int i=2;i<=len;i<<=1)
    {
        cp g=(cp){cos(2*pi/i),sin(2*pi/i)*sta};
        for(int j=i>>1;j>=0;j-=2)w[j]=w[j>>1];
        for(int j=1;j<i>>1;j+=2)w[j]=w[j-1]*g;
        for(int j=0;j<len;j+=i)
        {
            cp *a=x+j,*b=a+(i>>1);
            for(int l=0;l<i>>1;l++)
            {
                cp o=b[l]*w[l];
                b[l]=a[l]-o;
                a[l]=a[l]+o;
            }
        }
    }
    if(sta==-1)for(int i=0;i<len;i++)x[i].a/=len,x[i].b/=len;
}
cp x[maxfft],y[maxfft],z[maxfft];
void FFT(int *a,int *b,int n,int m,int *c)
{
    int len=1;
    while(len<n+m)len<<=1;
    fft_init(len);
    for(int i=0;i<len;i++)
    {
        int aa=i<n?a[i]:0,bb=i<m?b[i]:0;
        x[i]=(cp){(aa>>15),(aa&32767)},y[i]=(cp){(bb>>15),(bb&32767)};
    }
    fft(x,len,1),fft(y,len,1);
    for(int i=0;i<len;i++)
    {
        int j=len-1&len-i;
        z[i]=((x[i]+!x[j])*(y[i]-!y[j])+(x[i]-!x[j])*(y[i]+!y[j]))*(cp){0,-0.25};
    }
    fft(z,len,-1);
    for(int i=0;i<n+m-1;i++)
    {
        ll ta=(ll)(z[i].a+0.5)%mod;
        ta=(ta<<15)%mod;
        c[i]=ta;
    }
    for(int i=0;i<len;i++)
    {
        int j=len-1&len-i;
        z[i]=(x[i]-!x[j])*(y[i]-!y[j])*(cp){-0.25,0}+(x[i]+!x[j])*(y[i]+!y[j])*(cp){0,0.25};
    }
    fft(z,len,-1);
    for(int i=0;i<n+m-1;i++)
    {
        ll ta=(ll)(z[i].a+0.5)%mod,tb=(ll)(z[i].b+0.5)%mod;
        ta=(ta+(tb<<30))%mod;
        c[i]=(c[i]+ta)%mod;
    }
}
int temp1[maxfft];
void Poly_Inv(int *poly,int n,int *ans)
{
    ans[0]=Pow(poly[0],mod-2);
    for(int i=2;i<=n;i<<=1)
    {
        FFT(poly,ans,i,i/2,temp1);
        FFT(ans,temp1+i/2,i/2,i/2,temp1);
        for(int j=0;j<i/2;j++)ans[j+i/2]=temp1[j]==0?0:mod-temp1[j];
    }
}
int inv[maxn],fact[maxn],B[2*maxn];
void init(int n=100002)
{
    fact[0]=1;
    for(int i=1;i<=n;i++)fact[i]=mul(i,fact[i-1]);
    inv[1]=1;
    for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
    inv[0]=1;
    for(int i=1;i<=n;i++)inv[i]=mul(inv[i-1],inv[i]);
    int len=1;
    while(len<n-1)len<<=1;
    Poly_Inv(inv+1,len,B);
    for(int i=0;i<n;i++)B[i]=mul(B[i],fact[i]);
    B[1]++;
}
int T,K,m,a[22],b[22],f[2*maxn],g[maxn],h[maxn]; 
int main()
{
    init();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&K,&m);
        int n=1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            n=mul(n,Pow(a[i],b[i]));
        }
        for(int i=0;i<=K+2;i++)h[i]=1;
        for(int i=1;i<=m;i++)
        {
            int p=Pow(a[i],mod-2);
            for(int j=0;j<=K+2;j++)
            {
                h[j]=mul(h[j],1+mod-p);
                p=mul(p,a[i]);
            }
        }
        for(int i=0;i<=K;i++)f[i]=mul(B[K-i],inv[K-i]);
        int res=n;
        for(int i=0;i<=K+1;i++)
        {
            g[i]=mul(inv[i+1],res);
            res=mul(res,n);
        }
        reverse(g,g+K+2);
        FFT(f,g,K+1,K+2,f);
        for(int i=0;i<=K+1;i++)
            g[i]=mul(f[i+K],mul(fact[K],mul(inv[i],B[i])));
        int ans=0;
        for(int i=0;i<=K+1;i++)ans=add(ans,mul(g[i],h[i]));
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值