【BZOJ】3434: [Wc2014]时空穿梭-莫比乌斯反演

这篇博客详细介绍了如何解决BZOJ3434问题,即在多维直线上求整数点的最大数量。通过枚举极差和应用莫比乌斯反演,将问题转化为求解多项式并进行复杂度为O(m ln ln m + cmlnm + cmn + Tn^3m)的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:bzoj3434


题解

枚举每一维的极差 Δ x i \Delta x_i Δxi,设 d = g c d ( Δ x 1 , Δ x 2 , . . . , Δ x n ) d=gcd(\Delta x_1,\Delta x_2,...,\Delta x_n) d=gcd(Δx1,Δx2,...,Δxn),则这条直线上最多可以选出 d d d个整点(不包含起点)。

a n s = ∑ Δ x 1 = 1 m 1 ⋯ ∑ Δ x n = 1 m n ( d − 1 c − 2 ) ∏ i = 1 n ( m i − Δ x i ) ans=\sum\limits_{\Delta x_1=1}^{m_1}\dots\sum\limits_{\Delta x_n=1}^{m_n}\dbinom{d-1}{c-2}\prod\limits_{i=1}^n(m_i-\Delta x_i) ans=Δx1=1m1Δxn=1mn(c2d1)i=1n(miΔxi)

转成枚举 d d d

∑ d = 1 m ( d − 1 c − 2 ) ∑ Δ x 1 = 1 ⌊ m 1 d ⌋ ⋯ ∑ Δ x n = 1 ⌊ m n d ⌋ [ ( Δ x 1 , Δ x 2 , . . . , Δ x n ) = 1 ] ∏ i = 1 n ( m i − d Δ x i ) \sum\limits_{d=1}^m\dbinom{d-1}{c-2}\sum\limits_{\Delta x_1=1}^{\lfloor \frac{m_1}{d}\rfloor}\dots\sum\limits_{\Delta x_n=1}^{\lfloor \frac{m_n}{d}\rfloor}[(\Delta x_1,\Delta x_2,...,\Delta x_n)=1]\prod\limits_{i=1}^n(m_i-d\Delta x_i) d=1m(c2d1)Δx1=1dm1Δxn=1dmn[(Δx1,Δx2,...,Δxn)=1]i=1n(midΔxi)

莫比乌斯反演一下

∑ d = 1 m ( d − 1 c − 2 ) ∑ k = 1 ⌊ m d ⌋ μ ( k ) ∑ Δ x 1 = 1 ⌊ m 1 d k ⌋ ⋯ ∑ Δ x n = 1 ⌊ m n d k ⌋ ∏ i = 1 n ( m i − d k Δ x i ) \sum\limits_{d=1}^m\dbinom{d-1}{c-2}\sum\limits_{k=1}^{\lfloor\frac md \rfloor}\mu (k)\sum\limits_{\Delta x_1=1}^{\lfloor \frac{m_1}{dk}\rfloor}\dots\sum\limits_{\Delta x_n=1}^{\lfloor \frac{m_n}{dk}\rfloor}\prod\limits_{i=1}^n(m_i-dk\Delta x_i) d=1m(c2d1)k=1dmμ(k)Δx1=1dkm1Δxn=1dkmni=1n(midkΔxi)

T = d k T=dk T=dk,得到

∑ T = 1 m ( ∏ i = 1 n ∑ Δ x i = 1 ⌊ m i T ⌋ ( m i − T Δ x i ) ) ∑ d ∣ T ( d − 1 c − 2 ) μ ( T d ) \sum\limits_{T=1}^m(\prod\limits_{i=1}^n\sum\limits_{\Delta x_i=1}^{\lfloor \frac {m_i}{T}\rfloor}(m_i-T\Delta x_i))\sum\limits_{d|T}\binom{d-1}{c-2}\mu(\frac Td) T=1m(i=1nΔxi=1Tmi(miTΔxi))dT(c2d1)μ(dT)

G ( T ) = ∑ d ∣ T ( d − 1 c − 2 ) μ ( T d ) G(T)=\sum\limits_{d|T}\binom{d-1}{c-2}\mu(\frac Td) G(T)=dT(c2d1)μ(dT)可以 O ( m l n m ) O(mlnm) O(mlnm)预处理。

F ( T ) = ∏ i = 1 n ∑ Δ x i = 1 ⌊ m i T ⌋ ( m i − T Δ x i ) F(T)=\prod\limits_{i=1}^n\sum\limits_{\Delta x_i=1}^{\lfloor \frac {m_i}{T}\rfloor}(m_i-T\Delta x_i) F(T)=i=1nΔxi=1Tmi(miTΔxi)

  = ∏ i = 1 n ( m i ⌊ m i T ⌋ + T ( ⌊ m i T ⌋ + 1 ) ⌊ m i T ⌋ 2 ) \qquad\ =\prod\limits_{i=1}^n(m_i\lfloor\frac {m_i}{T}\rfloor+\dfrac{T(\lfloor\frac {m_i}{T}\rfloor+1)\lfloor\frac {m_i}{T}\rfloor}{2})  =i=1n(miTmi+2T(Tmi+1)Tmi)

⌊ m i T ⌋ \lfloor\frac {m_i}{T}\rfloor Tmi一定时, F ( T ) F(T) F(T)是一个关于 T T T n n n次多项式,所以 n m n\sqrt m nm 分块,每次 n 2 n^2 n2暴力处理 T i T^i Ti的系数 a i a_i ai

a n s = ∑ T = 1 m ∑ i = 0 n a i G ( T ) T i ans=\sum\limits_{T=1}^m\sum\limits_{i=0}^na_iG(T)T^i ans=T=1mi=0naiG(T)Ti

预处理出 G ( T ) T i G(T)T^i G(T)Ti的前缀和即可。

复杂度: O ( m   l n   l n m + c m ln ⁡ m + c m n + T n 3 m ) O(m\ ln\ ln m+cm\ln m+cmn+Tn^3\sqrt m) O(m ln lnm+cmlnm+cmn+Tn3m )


代码

#include<bits/stdc++.h>
#define mem(f,x) memset(f,x,sizeof(f))
typedef long long ll;
using namespace std;
const int N=1e5+10,mod=10007;

int tk,mxc,mxm,mn,ans,C[N][21],tmp[12];
int mu[N],g[21][N],f[21][12][N],p[N],num;bool pri[N];

char cp;
inline void rd(int &x)
{
    cp=getchar();x=0;
    for(;!isdigit(cp);cp=getchar());
    for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
}

inline void upp(int &x,int y){if(y>x) x=y;}
inline void dnn(int &x,int y){if(y<x) x=y;}
inline void ad(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void dc(int &x,int y){x-=y;if(x<0) x+=mod;}
inline int adi(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int dci(int x,int y){x-=y;return x<0?x+mod:x;}

inline void pre()
{
    int c,i,j,k,res;mu[1]=1;
    for(i=2;i<=mxm;++i){
        if(!pri[i]) p[++num]=i,mu[i]=-1;
        for(j=1;j<=num && (res=i*p[j])<=mxm;++j){
            pri[res]=true;if(i%p[j]==0) break;
            mu[res]=-mu[i];
        }
    }
    C[0][0]=1;
    for(i=1;i<=mxm;++i){
    	C[i][0]=1;
    	for(j=1;j<=mxc;++j) C[i][j]=adi(C[i-1][j-1],C[i-1][j]);
	}
	for(c=2;c<=mxc;++c){
        for(i=1;i<=mxm;++i){
            res=C[i-1][c-2];
            for(j=1,k=i;k<=mxm;++j,k+=i) if(mu[j])
                mu[j]<0?dc(g[c][k],res):ad(g[c][k],res);
        }
    }
    for(c=2;c<=mxc;++c){
       for(i=1;i<=mxm;++i){
          res=g[c][i];
          for(j=0;j<=11;++j){
            f[c][j][i]=adi(res,f[c][j][i-1]);
            res=(res*i)%mod;
          }
       }
    }
}

struct P{
    int n,c,m[12];

    inline void init()
    {
        rd(n);rd(c);upp(mxc,c);
        for(int i=1;i<=n;++i){rd(m[i]);upp(mxm,m[i]);}
    }

    inline void mk(int x)
    {
        int i,j,a,b;mem(tmp,0);tmp[0]=1;
        for(i=1;i<=n;++i){
            j=m[i]/x;
            a=mod-((ll)j*(j+1)/2)%mod;
            if(a==mod) a=0;
            b=(ll)j*m[i]%mod;
            for(j=n;j;--j) tmp[j]=adi(tmp[j]*b%mod,tmp[j-1]*a%mod);
            tmp[0]=tmp[0]*b%mod;
        }
    }

    inline void sol()
    {
        int i,j,k;ans=0;mn=2e9;
        for(i=1;i<=n;++i) dnn(mn,m[i]);
        for(i=1;i<=mn;i=j+1){
            for(j=mn,k=1;k<=n;++k) dnn(j,m[k]/(m[k]/i));
            for(mk(i),k=0;k<=n;++k) ad(ans,tmp[k]*dci(f[c][k][j],f[c][k][i-1])%mod);
        }
        printf("%d\n",ans);
    }
}q[1005];

int main(){
    int i,j;rd(tk);
    for(i=1;i<=tk;++i) q[i].init();
    pre();
    for(i=1;i<=tk;++i) q[i].sol();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值