51nod 1575 Gcd and Lcm【Min_25筛】

题目描述:

给出 n ≤ 1 0 9 n\le10^9 n109,求:
∑ i = 1 n ∑ j = 1 i ∑ k = 1 i [ ( i , j ) , ( i , k ) ]     m o d    2 32 \sum_{i=1}^n\sum_{j=1}^i\sum_{k=1}^i [(i,j),(i,k)]~~~\mod 2^{32} i=1nj=1ik=1i[(i,j),(i,k)]   mod232

题目分析:

很好,又是一道筛题,我们开始推式子:

推式子内容详见tangjz的答案,以及佐理慧的blog,省略1万字。。

然后我们自闭了。

然后有人告诉我们 ∑ j = 1 i ∑ k = 1 i [ ( i , j ) , ( i , k ) ] \sum_{j=1}^i\sum_{k=1}^i [(i,j),(i,k)] j=1ik=1i[(i,j),(i,k)]是一个关于 i i i的积性函数。
F ( P k ) = ( 2 k + 1 ) ( P 2 k − P 2 k − 1 ) + P k − 1 F(P^k)=(2k+1)(P^{2k}-P^{2k-1})+P^{k-1} F(Pk)=(2k+1)(P2kP2k1)+Pk1
很好,直接上Min_25筛。
。。。。。。

Code:

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef unsigned int ui;
const ui inv3 = 2863311531u;
int T,n,m,sn,a[maxn];
ui s[3][maxn],f[maxn];
inline int ID(int x){return x<=sn?x:m-n/x+1;}
int main()
{
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n),sn=sqrt(n),m=0;
		for(int i=1;i<=n;i++) a[++m]=i=n/(n/i),s[0][m]=i-1,s[1][m]=1ll*i*(i+1)/2-1,s[2][m]=1ll*i*(i+1)/2*(2*i+1)*inv3-1;
		//1到sn必然在a中,即a[i<=sn]=i
		for(int i=2;i<=sn;i++) if(s[0][i]^s[0][i-1])//已经筛去了<i的质数,若s[0][i]!=s[0][i-1],说明i是质数
			for(int j=m;a[j]>=i*i;j--)
				s[0][j]-=s[0][ID(a[j]/i)]-s[0][i-1],
				s[1][j]-=i*(s[1][ID(a[j]/i)]-s[1][i-1]),
				s[2][j]-=i*i*(s[2][ID(a[j]/i)]-s[2][i-1]);
		for(int i=1;i<=m;i++) f[i]=3*s[2][i]-3*s[1][i]+s[0][i];//f(p)=3*p^2-3*p+1
		for(int i=sn;i>1;i--) if(s[0][i]^s[0][i-1])//Min_25筛非递归写法
			for(int j=m;a[j]>=i*i;j--)
				for(ui k=1,p0=1,p1=i,sp=3*s[2][i]-3*s[1][i]+s[0][i];1ll*p1*i<=a[j];k++,p0=p1,p1*=i)
					f[j]+=((2*k+1)*p1*p0*(i-1)+p0)*(f[ID(a[j]/p1)]-sp)+(2*k+3)*p1*p1*i*(i-1)+p1;
		printf("%u\n",f[m]+1);
	}
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值