小米oj118 Grizzly and GCD 数论

23 篇文章 0 订阅
20 篇文章 0 订阅

Description


给定n,a,b,求这个东西 { ∑ m = 0 n [ ( n m ) % 2 ] } ∑ i = 1 n ∑ j = 1 i − 1 gcd ⁡ ( a i − b i , a j − b j ) \left\{\sum_{m=0}^n\left[{\binom{n}{m}} \%2\right]\right\}\sum_{i=1}^n\sum_{j=1}^{i-1}\gcd\left(a^i-b^i,a^j-b^j\right) {m=0n[(mn)%2]}i=1nj=1i1gcd(aibi,ajbj)
n ≤ 1 0 5 , gcd ⁡ ( a , b ) = 1 n\le10^5,\gcd(a,b)=1 n105,gcd(a,b)=1

Solution


小米竟然还有oj,我火星了

先看后面那一坨
说一个结论,就是当 gcd ⁡ ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1时, gcd ⁡ ( a n − b n , a m − b m ) = a gcd ⁡ ( n , m ) − b gcd ⁡ ( n , m ) \gcd\left(a^n-b^n,a^m-b^m\right)=a^{\gcd\left(n,m\right)}-b^{\gcd\left(n,m\right)} gcd(anbn,ambm)=agcd(n,m)bgcd(n,m)
这个的证明可以考虑设 d = gcd ⁡ ( n , m ) d=\gcd\left(n,m\right) d=gcd(n,m),然后提取一个(a-b)暴力逆展开,这里就不写了(滑稽
于是就看起来可做了,化成下面这个样子 1 2 [ ∑ d = 1 n ( a d − b d ) ∑ x = 1 ⌊ n d ⌋ μ ( x ) ( ⌊ n d x ⌋ ) 2 ] − ∑ i = 1 n ( a i − b i ) \frac{1}{2}\left[\sum_{d=1}^n\left(a^d-b^d\right)\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\mu(x){\left(\lfloor\frac{n}{dx}\rfloor\right)}^2\right]-\sum_{i=1}^{n}\left(a^i-b^i\right) 21d=1n(adbd)x=1dnμ(x)(dxn)2i=1n(aibi)
实际上还可以继续化变成O(n)预处理根号求的做法,但是我们这样就已经可以跑过了

然后看看前面那一坨,我们发现实际上就是统计组合数某一行的奇偶性
再说一个结论,就是 ( n m ) ≡ [ m & n = n ] ( m o d 2 ) \binom{n}{m}\equiv[m\&n=n]\pmod2 (mn)[m&n=n](mod2)
这个的证明可以考虑归纳一下,然后大力讨论四种情况即可

于是就做完了。。

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

typedef long long LL;
const int MOD=1e9+7;
const int ny2=(MOD+1)/2;
const int N=200005;

LL ta[N],tb[N],mu[N];
int p[N];

bool np[N];

void upd(LL &x,LL v) {
	x+=v; (x>=MOD)?(x-=MOD):0;
}

void pre(int n) {
	mu[1]=1;
	rep(i,2,n) {
		if (!np[i]) p[++p[0]]=i,mu[i]=MOD-1;
		for (int j=1;i*p[j]<=n&&j<=p[0];++j) {
			np[i*p[j]]=1;
			if (i%p[j]==0) {mu[i*p[j]]=0; break;}
			mu[i*p[j]]=MOD-mu[i];
		}
	}
}

LL ksm(LL x,LL dep) {
	LL res=1;
	for (;dep;dep>>=1) {
		(dep&1)?(res=res*x%MOD):0;
		x=x*x%MOD;
	}
	return res;
}

int main(void) {
	int n,a,b; scanf("%d%d%d",&n,&a,&b);
	pre(n); LL ans=0,wjp=0; ta[0]=tb[0]=1;
	rep(i,1,n) ta[i]=ta[i-1]*a%MOD,tb[i]=tb[i-1]*b%MOD;
	rep(i,0,n) if ((i&n)==i) upd(wjp,1);
	rep(d,1,n) {
		LL tmp=0;
		rep(x,1,(n/d)) {
			upd(tmp,mu[x]*(n/(d*x))%MOD*(n/(d*x))%MOD);
		}
		tmp=tmp*(ta[d]-tb[d]+MOD)%MOD;
		upd(ans,tmp);
	}
	rep(i,1,n) upd(ans,tb[i]),upd(ans,MOD-ta[i]);
	ans=ans*ny2%MOD;
	printf("%lld\n", wjp*ans%MOD);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值