1 条题解

  • 0
    @ 2025-8-24 22:24:22

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar longfei
    **

    搬运于2025-08-24 22:24:22,当前版本为作者最后更新于2020-11-18 00:43:29,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题解 P6826 【「EZEC-4」月下轻花舞】

    @我谔谔 大佬的分kk大小和前缀和优化思路对我很有启发。但我推式子的过程和大佬有所不同。

    推式子思路

    注意到 logijZ\left \lceil \log_{i}j \right \rceil \in Z,所以将 logij\left \lceil \log_{i}j \right \rceil 以求和号的形式写出来,然后通过交换求和号改变求和顺序,达到去掉大循环的目的。

    $$\sum_{i=l}^{r}(i-1)\sum_{j=1}^{n}\left \lceil \log_{i}j \right\rceil = \sum_{i=l}^{r}(i-1)\sum_{j=1}^{n}\sum_{k\geqslant 1}^{}\sum_{i^{k-1}<j}^{}1 $$

    式子的核心在于 ik1<ji^{k-1}<j 。最内层循环为 i,ki,k 时仍需要遍历计算。当最内层循环 jj 时,有

    $$\sum_{j=1}^{n}\sum_{i^{k-1}<j}^{}1=max(n-i^{k-1},0) $$

    于是要求的式子转化为

    $$\sum_{i=l}^{r}(i-1)\sum_{k\geqslant 1}max(n-i^{k-1},0) $$

    (i1)max(nik1,0)(i-1)max(n-i^{k-1},0) 有意义时,ik1ni^{k-1}\leqslant n,即 klogin+1k\leqslant log_{i}n+1 。记t=login+1t=log_{i}n+1,有

    $$\sum_{i=l}^{r}(i-1)\sum_{k\geqslant 1}max(n-i^{k-1},0)=\sum_{i=l}^{r}\sum_{k\leqslant t}(i-1)(n-i^{k-1}) $$$$=\sum_{i=l}^{r}\sum_{k\leqslant t}(i-1)n -\sum_{i=l}^{r}\sum_{k\leqslant t}(i^{k}- i^{k-1})=\sum_{i=l}^{r}(i-1)nt-\sum_{i=l}^{r}(i^{t}-1) $$$$=\sum_{i=l}^{r}(i-1)nt-\sum_{i=l}^{r}i^{t}+(r-l+1) $$

    枚举 kk 的值,k=1,2,3,4k=1,2,3,4时手算求和公式,k5k\geqslant5时用前缀和数组。处理的区间为(n,r](n,r],(n,n](\sqrt[]{n},n],(n3,n](\sqrt[3]{n},\sqrt[]{n}],(n4,n3](\sqrt[4]{n},\sqrt[3]{n}]... 最终处理到 ll

    下面附上代码。需要注意诸多细节,在文中说明。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define MAXN (1<<16)+5//开到2*10^18的四次根 
    #define MAXK 62
    #define MAXT 100005//离线,其实可以不用 
    #define MOD 998244353
    #define re register long long
    ll s[MAXN][MAXK];//前缀和数组 
    ll l1[MAXT],r1[MAXT],n1[MAXT];//离线取最大的n,其实没必要 
    ll base[MAXN];//辅助预处理,记录下标的幂次 
    ll fj[MAXK];//记录n^(1/下标) 
    ll t,l,r,n,k,maxn;
    ll gsc(ll a,ll b){//取模乘法 
    	a%=MOD;b%=MOD;
    	return (a*b)%MOD;
    }
    ll dev(ll a,ll b){//取模除法 
    	while(a%b!=0)a+=MOD;
    	return a/b;
    }
    void solve(ll l,ll r,ll n){ 
    	ll ans=r-l+1;
    	memset(fj,0,sizeof(fj));
    	for(re i=1;i<=n;i++){
    		fj[i]=pow(n,1.00/i);
    		if(fj[i]==1)break;//太小的用不到 
    	}
    	ll inf=l;
    	if(r>fj[4]){//手算公式的需要 
    		if(r>fj[3]){
    			if(r>fj[2]){
    				if(r>n){
    					inf=n+1;
    					inf=max(l,inf);
    					if(l<=r){//处理下界 
    						ll tmp=dev(gsc(r+inf,r-inf+1),2);
    						ans=(ans+dev(gsc(n,gsc(r+inf-2,r-inf+1)),2)-tmp)%MOD;
    						while(ans<0)ans+=MOD;
    						r=n;//改变上标,大于n的已处理完毕 
    					}
    				}
    				inf=fj[2]+1;
    				inf=max(l,inf);
    				if(l<=r){
    					ll tmp=(dev(gsc(gsc(r,r+1),2*r+1),6)-dev(gsc(gsc(inf-1,inf),2*inf-1),6))%MOD;
    					ans=(ans+gsc(n,gsc(r+inf-2,r-inf+1))-tmp)%MOD;
    					while(ans<0)ans+=MOD;
    					r=fj[2];
    				}
    			}
    			inf=fj[3]+1;
    			inf=max(l,inf);
    			if(l<=r){
    				ll tmp=(dev(gsc(r,gsc(r,gsc(r+1,r+1))),4)-dev(gsc(inf,gsc(inf,gsc(inf-1,inf-1))),4))%MOD;
    				ans=(ans+(dev(gsc(n,gsc(r+inf-2,r-inf+1)),2)*3)%MOD-tmp)%MOD;
    				while(ans<0)ans+=MOD;
    				r=fj[3];
    			}
    		}
    		inf=fj[4]+1;
    		inf=max(l,inf);
    		if(l<=r){
    			ll tmp=dev(gsc(dev(gsc(gsc(r,r+1),2*r+1),6),gsc(gsc(r,r),3)+gsc(3,r)-1),5)-dev(gsc(dev(gsc(gsc(inf-1,inf),2*inf-1),6),gsc(gsc(inf-1,inf-1),3)+gsc(3,inf-1)-1),5);
    			ans=(ans+(dev(gsc(n,gsc(r+inf-2,r-inf+1)),2)*4)%MOD-tmp)%MOD;
    			while(ans<0)ans+=MOD;
    			r=fj[4];
    		}
    	}
    	for(re t=5;t<=log(n)/log(2)+1;t++){
    		inf=fj[t]+1;
    		inf=max(l,inf);
    		if(l>r)break;//处理下界,当当前处理区间下界>=l的时候就退出 
    		if(r>fj[t]){
    			ll tmp=(s[r][t]-s[inf-1][t]+MOD)%MOD;
    			ans=ans+gsc(dev(gsc(n,gsc(r+inf-2,r-inf+1)),2),t)-tmp;
    			while(ans<0)ans+=MOD;
    			r=fj[t];
    		}
    	}
    	while(ans<0)ans+=MOD;
    	printf("%lld\n",ans%MOD);
    }
    int main(){
    	scanf("%lld",&t);
    	for(re i=1;i<=t;i++)scanf("%lld%lld%lld",&l1[i],&r1[i],&n1[i]),maxn=max(maxn,n1[i]);
    	for(re i=1;i<=(1<<16);i++){
    		base[i]=(i*i)%MOD;
    		base[i]=(base[i]*base[i])%MOD;
    		base[i]*=i;base[i]%=MOD;
    	}
    	for(re j=5;j<=log(maxn)/log(2)+1;j++){
    		for(re i=1;i<=(1<<16);i++){
    			s[i][j]=(s[i-1][j]+base[i])%MOD;
    			base[i]=(base[i]*i)%MOD;
    		}
    	}//预处理 
    	for(re q=1;q<=t;q++)solve(l1[q],r1[q],n1[q]);
    }
    
    • 1

    信息

    ID
    5737
    时间
    1000~1500ms
    内存
    128MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者