【LOJ #3069】「2019 集训队互测 Day 1」整点计数(min_25筛)

传送门

首先是这样一道
虽然看起很像但实际上发现完全没法套过来


先只考虑第一象限,然后+1乘四即可

考虑将平方数表示成一个高斯整数与其共轭数的积
r 2 = a 2 + b 2 = ( a + b i ) ∗ ( a − b i ) r^2=a^2+b^2=(a+bi)*(a-bi) r2=a2+b2=(a+bi)(abi)
显然每个 ( a + b i ) (a+bi) (a+bi)对应一个坐标系上的点

费马平方和定理:奇质数 p p p 可以表示为两个正整数 a , b a, b a,b 的平方和 p = a 2 + b 2 p = a^2 + b^2 p=a2+b2 ,当且
仅当 p ≡ 1 m o d    4 p ≡ 1 \mod 4 p1mod4 ,并且这样的表示若存在,在不计较排列顺序的情况下,是唯一的。

由此可以得到对于一个质数且 p ≡ 1 m o d    4 p\equiv 1\mod 4 p1mod4
我们会将其唯一的拆分成一个 ( a + b i ) ∗ ( a − b i ) (a+bi)*(a-bi) (a+bi)(abi)
而对于 p ≡ 3 m o d    4 p\equiv 3\mod 4 p3mod4的,只能作为整数而无法拆分成高斯整数

于是考虑对于一个数
考虑每个质因子拆分成共轭的高斯整数
再把所有的高斯整数与其共轭数分成两部分即可
r 2 = ∏ p i k i r^2=\prod p_i^{k_i} r2=piki
对于每个质因子可以分别考虑
对于 p ≡ 3 m o d    4 p\equiv 3\mod 4 p3mod4 k k k次幂
显然只有当 k k k为偶数时有一种情况

所以可以看做没有贡献
对于 p ≡ 1 p\equiv1 p1
可以拆成 ( a + b i ) x ( a − b i ) k − x , ( a + b i ) k − x ( a − b i ) x (a+bi)^x(a-bi)^{k-x},(a+b_i)^{k-x}(a-bi)^x (a+bi)x(abi)kx,(a+bi)kx(abi)x两部分
k + 1 k+1 k+1种情况

于是点数为 f ( r ) = 4 ∏ ( 1 + [ p i ≡ 1 m o d    4 ] ∗ k i ) , r 2 = ∏ i p i k i f(r)=4\prod(1+[p_i\equiv 1\mod 4]*k_i),r^2=\prod_{i}p_i^{k_i} f(r)=4(1+[pi1mod4]ki),r2=ipiki

考虑要求的答案是 ∑ i f ( i ) k = 4 k ∑ g ( i ) k \sum_{i}f(i)^k=4^k\sum g(i)^k if(i)k=4kg(i)k
显然有上面的分析可得 g g g为积性函数

于是考虑用 m i n 25 min_{25} min25
对于第一部分要求出前缀 ≡ 1 和 ≡ 3 m o d    4 \equiv1和\equiv3\mod 4 13mod4的质数个数
分别设为 c n t 0 , c n t 1 cnt_0,cnt_1 cnt0,cnt1,有
(来自 x y x xyx xyx的解题报告)
在这里插入图片描述

对于第二部分
一个 p k p^k pk的点值是 2 k + 1 ( p ≡ 1 ) / 1 ( p ≡ 3 ) 2k+1(p\equiv 1)/1(p\equiv 3) 2k+1(p1)/1(p3)
于是直接筛即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define y1 shinkle
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	s[top+1]='\0';return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
int mod;
inline int add(int a,int b){return (a+b)>=mod?(a+b-mod):(a+b);}
inline int dec(int a,int b){return (a<b)?(a-b+mod):(a-b);}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){a=(a+b)>=mod?(a+b-mod):(a+b);}
inline void Dec(int &a,int b){a=(a<b)?(a-b+mod):(a-b);}
inline void Mul(int &a,int b){static ll r;r=(ll)a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,ll b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){x%=mod;return (x<0)?x+mod:x;}
cs int N=1000005;
int ln;
ll n,k;
int pr[N],tot,pw[121];
bool vis[N];
inline void init_sieve(){
	for(int i=1;i<=120;i++)pw[i]=ksm(i,k);
	for(int i=2;i<N;i++){
		if(!vis[i])pr[++tot]=i;
		for(int j=1;j<=tot&&i*pr[j]<N;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0)break;
		}
	}
}
ll f1[N],f3[N],g1[N],g3[N];
int f[N],g[N];
inline void init_min_25(){
	ln=sqrt(n);
	for(int i=1;i<=ln;i++){
		f1[i]=(i+3)/4-1,f3[i]=(i+1)/4;
		g1[i]=(n/i+3)/4-1,g3[i]=(n/i+1)/4;
	}
	for(int c1=0,c3=0,tt=1;pr[tt]<=ln;tt++){
		int p=pr[tt];int w1=ln/p,w2=min((ll)ln,n/p/p);ll nw=n/p;
		if(p%4==1){
			for(int i=1;i<=w1;i++)
			g1[i]+=c1-g1[i*p],
			g3[i]+=c3-g3[i*p];
			for(int i=w1+1;i<=w2;i++)
			g1[i]+=c1-f1[nw/i],
			g3[i]+=c3-f3[nw/i];
			for(int i=ln;i>=(ll)p*p;i--)
			f1[i]+=c1-f1[i/p],
			f3[i]+=c3-f3[i/p];
			c1++;
		}
		else if(p%4==3){
			for(int i=1;i<=w1;i++)
			g1[i]+=c3-g3[i*p],
			g3[i]+=c1-g1[i*p];
			for(int i=w1+1;i<=w2;i++)
			g1[i]+=c3-f3[nw/i],
			g3[i]+=c1-f1[nw/i];
			for(int i=ln;i>=(ll)p*p;i--)
			f1[i]+=c3-f3[i/p],
			f3[i]+=c1-f1[i/p];
			c3++;
		}
	}
	for(int i=1;i<=ln;i++){
		f[i]=add(fix(f3[i]),mul(fix(f1[i]),pw[3]));
		g[i]=add(fix(g3[i]),mul(fix(g1[i]),pw[3]));
	}
}
inline int F(ll x){
	return x<=ln?f[x]:g[n/x];
}
inline int ff(int p,int e){return (p&3)==1?pw[e*2+1]:1;}
inline int solve(ll n,int p){
	int res=dec(F(n),f[pr[p-1]]);if(p==1)res++;
	for(int j=p;(ll)pr[j]*pr[j]<=n;j++)
	for(ll mt=pr[j],e=1;mt*pr[j]<=n;e++,mt*=pr[j]){
		Add(res,mul(solve(n/mt,j+1),ff(pr[j],e)));
		Add(res,ff(pr[j],e+1));
	}return res;
}
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	n=readll(),k=readll(),mod=read();
	init_sieve(),init_min_25();
	cout<<mul(pw[4],solve(n,1)+1)<<'\n';
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值