[BZOJ3601]一个人的数论-题解

题目地址

题意简述

给你 n , d n,d n,d,求下面式子在 m o d   1 0 9 + 7 {\rm mod}\ 10^9+7 mod 109+7意义下的值。

∑ i = 1 n [ g c d ( i , n ) = 1 ] i d \sum_{i=1}^n[gcd(i,n)=1]i^d i=1n[gcd(i,n)=1]id

其中 n n n特别大,所以我们给你一个 w w w,然后给你两个数组 p i , c i p_i,c_i pi,ci,其中:

n = ∏ i = 1 w p i c i n=\prod_{i=1}^wp_i^{c_i} n=i=1wpici

d ≤ 100 , w ≤ 1000 , p i , c i ≤ 1 0 9 d\leq 100,w\leq 1000,p_i,c_i\leq 10^9 d100,w1000,pi,ci109


我们仍旧先推一波式子:

a n s = ∑ i = 1 n [ g c d ( i , n ) = 1 ] i d = ∑ i = 1 n i d ∑ j ∣ i , j ∣ n μ ( j ) = ∑ j = 1 n μ ( j ) ∑ j ∣ i n i d = ∑ j = 1 n μ ( j ) ∑ i = 1 ⌊ n j ⌋ ( i j ) d = ∑ j = 1 n μ ( j ) j d ∑ i = 1 ⌊ n j ⌋ i d \begin{aligned} ans=&\sum_{i=1}^n[gcd(i,n)=1]i^d \\ =& \sum_{i=1}^ni^d\sum_{j|i,j|n}\mu(j) \\ =& \sum_{j=1}^n\mu(j)\sum_{j|i}^ni^d \\ =& \sum_{j=1}^n\mu(j)\sum_{i=1}^{\lfloor\frac{n}{j}\rfloor}(ij)^d \\ =&\sum_{j=1}^n\mu(j)j^d\sum_{i=1}^{\lfloor\frac{n}{j}\rfloor}i^d \end{aligned} ans=====i=1n[gcd(i,n)=1]idi=1nidji,jnμ(j)j=1nμ(j)jinidj=1nμ(j)i=1jn(ij)dj=1nμ(j)jdi=1jnid

后面部分就是自然数幂的前缀和,拉格朗日差值就可以了,在 O ( d l o g d ) O(dlogd) O(dlogd)时间内求出,而前面是可以杜教筛的:

∑ j ∣ n μ ( j ) j d = ( μ ⋅ i d d ) ∗ 1 \begin{aligned} \sum_{j|n}\mu(j)j^d=&(\mu\cdot id^d)*\mathbf1 \end{aligned} jnμ(j)jd=(μidd)1

我们令 f = ( μ ⋅ i d d ) ∗ 1 , g = i d d f=(\mu\cdot id^d)*\mathbf1,g=id^d f=(μidd)1,g=idd,然后 f ∗ g f*g fg就等于:

∑ j ∣ n μ ( j ) j d ( n j ) d = n d ∑ j ∣ n μ ( j ) = n d [ n = 1 ] = [ n = 1 ] = ϵ \sum_{j|n}\mu(j)j^d(\frac{n}{j})^d=n^d\sum_{j|n}\mu(j)=n^d[n=1]=[n=1]=\epsilon jnμ(j)jd(jn)d=ndjnμ(j)=nd[n=1]=[n=1]=ϵ

所以 f = ( μ ⋅ i d d ) ∗ 1 , g = i d d , h = ϵ f=(\mu\cdot id^d)*\mathbf1,g=id^d,h=\epsilon f=(μidd)1,g=idd,h=ϵ,然后套入杜教筛公式即可:

S ( n ) = 1 − ∑ i = 2 n i d S ( ⌊ n i ⌋ ) S(n)=1-\sum_{i=2}^ni^dS(\lfloor\frac{n}{i}\rfloor) S(n)=1i=2nidS(in)

然后就可以在 O ( n 2 3 d l o g d ) O(n^{\frac{2}{3}}dlogd) O(n32dlogd)的时间内解决了。


等等, n n n好像有 1 0 10000... 10^{10000...} 1010000...左右,-_-||。

但是不是就这样束手就擒,打暴力去了呢?

不,我们离正解还差一步了。


但是,我们根据拉格朗日差值的经验可以知道, ∑ i = 1 n i d \sum_{i=1}^ni^d i=1nid为一个 d + 1 d+1 d+1次多项式,那么我们令 g ( x ) = ∑ i = 1 x i d g(x)=\sum_{i=1}^xi^d g(x)=i=1xid,同时我们也可以知道 g ( x ) = ∑ i = 1 d + 1 a i x i g(x)=\sum_{i=1}^{d+1}a_ix^i g(x)=i=1d+1aixi,假设我们求出了所有 a i a_i ai,我们将其带入式子,看看有没有什么奇妙的反应:

a n s = ∑ j = 1 n μ ( j ) j d ∑ i = 1 ⌊ n j ⌋ i d = ∑ j = 1 n μ ( j ) j d ∑ i = 1 d + 1 a i ( ⌊ n j ⌋ ) i = ∑ i = 1 d + 1 a i ∑ j ∣ n μ ( j ) j d ( ⌊ n j ⌋ ) i \begin{aligned} ans=&\sum_{j=1}^n\mu(j)j^d\sum_{i=1}^{\lfloor\frac{n}{j}\rfloor}i^d \\ =&\sum_{j=1}^n\mu(j)j^d\sum_{i=1}^{d+1}a_i\left(\left\lfloor\frac{n}{j}\right\rfloor\right)^i \\ =&\sum_{i=1}^{d+1}a_i\sum_{j|n}\mu(j)j^d\left(\left\lfloor\frac{n}{j}\right\rfloor\right)^i \end{aligned} ans===j=1nμ(j)jdi=1jnidj=1nμ(j)jdi=1d+1ai(jn)ii=1d+1aijnμ(j)jd(jn)i

现在我们主要是要解决后半部分的快速求法,我们令 f ( i ) = ∑ j ∣ n μ ( j ) j d ( ⌊ n j ⌋ ) i f(i)=\sum_{j|n}\mu(j)j^d\left(\left\lfloor\frac{n}{j}\right\rfloor\right)^i f(i)=jnμ(j)jd(jn)i,那么我们知道 f = ( μ ⋅ i d d ) ∗ i d i f=(\mu\cdot id^d)*id^i f=(μidd)idi,那么根据 μ , i d k \mu,id^k μ,idk都为积性函数,而积性函数的狄利克雷卷积都为积性函数,所以我们可以知道 f f f也是一个积性函数。

这里,我们看,题目都将 n n n的质因数帮我们分解好了凯森(ノ ̄▽ ̄),所以我们将质因数分开考虑,因为 f ( n ) = ∏ f ( p i c i ) f(n)=\prod f(p_i^{c_i}) f(n)=f(pici),所以此时,我们只需知道 f ( p c ) f(p^c) f(pc)如何计算:

我们看原式
∑ j ∣ p c μ ( j ) j d ( ⌊ n j ⌋ ) i = ∑ k = 0 c μ ( p k ) ( p k ) d ( ⌊ n p k ⌋ ) i \sum_{j|p^c}\mu(j)j^d\left(\left\lfloor\frac{n}{j}\right\rfloor\right)^i=\sum_{k=0}^c\mu(p^k)(p^k)^d\left(\left\lfloor\frac{n}{p^k}\right\rfloor\right)^i jpcμ(j)jd(jn)i=k=0cμ(pk)(pk)d(pkn)i

而根据 μ \mu μ的定义,我们知道当 k > 1 k>1 k>1时的时候 μ ( p k ) = 0 \mu(p^k)=0 μ(pk)=0,所以 k = 0 , 1 k=0,1 k=0,1,那么 f ( p c ) f(p^c) f(pc)就等于:

( p c ) i − p d ( p c − 1 ) i = p c i − p c i − i + d (p^c)^i-p^d(p^{c-1})^i=p^{ci}-p^{ci-i+d} (pc)ipd(pc1)i=pcipcii+d

那么枚举 a i a_i ai,然后枚举 p j p_j pj,然后算就用快速幂,复杂度就是 O ( d w l o g ( 1 0 9 + 6 ) ) O(dwlog(10^9+6)) O(dwlog(109+6))(因为根据欧拉定理和费马小定理,我们可以将指数 m o d   1 0 9 + 6 {\rm mod}\ 10^9+6 mod 109+6)。

好啦,就解决啦!ヾ(@^▽^@)ノ


等等辣QAQ, a i a_i ai好像还没说怎么求-_-||。

其实,我们知道它是一个 d + 1 d+1 d+1次多项式的系数,那么高斯消元就好啦,我们列出 g ( 1 ) ∼ g ( d + 1 ) g(1)\sim g(d+1) g(1)g(d+1)的方程即可。

前面回顾: g ( x ) = ∑ i = 1 d + 1 a i x i g(x)=\sum_{i=1}^{d+1}a_ix^i g(x)=i=1d+1aixi

这个方程组的初始化,我们每次枚举 x x x,然后用快速幂计算出当前的 g ( x ) g(x) g(x)的值,然后枚举 a i a_i ai,依次计算出 x i x^i xi作为系数即可,然后就是高斯消元板子啦~~


丑陋的加调了半天的代码_(¦3」∠)_:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e3+10,M=1e2+10;
const ll Mod=1e9+7;
int d,w;
ll fpow(ll a,ll b){
	ll res=1;
	for(;b;b>>=1,a=(a*a)%Mod)
		if(b&1)res=(res*a)%Mod;
	return res;
}
ll A[M][M],X[M],P[N],C[N];
void Guass(){
	int D=d+1;
	for(ll i=0,sum=0,x;i<=D;i++){
		x=1;sum=(sum+fpow(i,d))%Mod;
		A[i][D+1]=sum;
		for(ll j=0;j<=D;j++){
			A[i][j]=x;x=(x*i)%Mod;	
		}
	}
	for(int now=0,pos;now<=D;now++){
		pos=now;
		if(!A[pos][now])
			for(int i=now+1;i<=D;i++)
				if(A[i][now]){pos=i;break;}
		if(pos!=now)swap(A[now],A[pos]);
		ll inv=fpow(A[now][now],Mod-2);
		for(int i=now+1;i<=D;i++){
			ll tt=(A[i][now]*inv)%Mod;
			for(int j=0;j<=D+1;j++){
				A[i][j]=(A[i][j]-A[now][j]*tt%Mod)%Mod;
				if(A[i][j]<0)A[i][j]+=Mod;
			}
		}
	}
	for(int i=D;i>=0;i--){
		for(int j=D;j>=i+1;j--){
			A[i][D+1]=(A[i][D+1]-A[i][j]*X[j]%Mod)%Mod;
			if(A[i][D+1]<0)A[i][D+1]+=Mod;
		}
		X[i]=A[i][D+1]*fpow(A[i][i],Mod-2)%Mod;
	}
}
ll GetH(ll a,ll b){
	ll p1=C[b]*a%(Mod-1);
	ll p2=(p1+d-a)%(Mod-1);if(p2<0)p2+=(Mod-1);
	ll ans=(fpow(P[b],p1)-fpow(P[b],p2))%Mod;
	if(ans<0)ans+=Mod;
	return ans;
}
ll ans;
int main(){
	scanf("%d%d",&d,&w);
	Guass();
	for(int i=1;i<=w;i++)scanf("%lld%lld",&P[i],&C[i]);
	for(int i=0,D=d+1;i<=D;i++){
		ll xx=X[i];
		for(int j=1;j<=w;j++)xx=(xx*GetH(i,j))%Mod;
		ans=(ans+xx)%Mod;
	}
	printf("%lld\n",ans);
	return 0;
}

End

元旦节只放一天,1月1日还要在学校度过,惨兮兮QWQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值