JZOJ 5508 距离

Description

在一个 k 维空间内,定义一个点的切比雪夫距离为
这里写代码片

求在k维空间内到原点的切比雪夫距离不超过 n 的所有点的到原点的切比雪夫距离之和。

Data Constraint

k<= 106 N <=109

Code

枚举 j 表示有j维到原点的距离不为 0 ,则这j维的符号可正可负,接着再枚举切比雪夫距离 i
通过简单的容斥可得方案数为2j( ij - (i1)j ),于是可以把答案表示出来了

Answer=j=1kCjk2j[i=1n(ij(i1)j)i]

=j=1kCjk2j(ij+1i=1n1ij)

=j=1kCjk2jij+1j=1kCjk2ji=1n1ij)

=j=1kCjk2jij+1i=1n1j=1kCjk(2i)j1kj)

=j=1kCjk2jij+1i=1n1j=1kCjk(2i)j1kj)

=j=1kCjk2jij+1i=1n1[(2i+1)j1]

左边那部分很好求,而 n1i=1[(2i+1)j1] 显然可以表示成一个 k +1项的关于 n 的函数,用拉格朗日插值法求解即可。
时间复杂度O( k log22 k <script type="math/tex" id="MathJax-Element-614">k</script>)。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)

using namespace std;
typedef long long ll;
const ll N=12e5,mo=1e9+7;

ll ksm(ll o,ll t)
{
    ll y=1;
    for(;t;t>>=1,o=o*o%mo)
    if(t&1)y=y*o%mo;
    return y;
}

ll jc[N],ny[N],w[N],k,n;

ll C(ll a,ll b)
{return jc[a]*ny[b]%mo*ny[a-b]%mo;}

int main()
{
    cin>>k>>n;
    fo(i,1,k+2)w[i]=(w[i-1]+ksm(2*i+1,k)+mo-1)%mo;
    jc[0]=ny[0]=jc[1]=ny[1]=1;
    fo(i,2,k+2)jc[i]=jc[i-1]*i%mo;
    ny[k+2]=ksm(jc[k+2],mo-2);
    fd(i,k+1,1)ny[i]=ny[i+1]*(i+1)%mo;
    ll ans=0,u=1,p=n%mo;
    fo(j,1,k){
        u=(u<<1)%mo; p=p*n%mo;
        ans=(ans+u*C(k,j)%mo*p)%mo;
    }
    ll zd=1,a2=0;
    --n;
    if(n>k+2){
    fo(i,1,k+2)zd=zd*(n-i)%mo;
    fo(i,1,k+2){
        ll op=zd*ksm(n-i,mo-2)%mo;
        op=op*ny[i-1]%mo;
        op=op*ny[k+2-i]%mo*((k+2-i)%2?-1:1);
        op=(op+mo)%mo;
        a2=(a2+op*w[i])%mo;
    }
    }else a2=w[n];
    ans=(ans-a2+mo)%mo;
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值