P1998 DGF 等比求和 题解

P1998 DGF 等比求和

题意:

给定数论函数 \(f\),定义 \(f^n\) 为 \(f\) 与自身做 \(n-1\) 次 Dirichlet 卷积。令 \(g = f + f^2 + \cdots + f^m\)。求 \(g(1)\) 到 \(g(n)\) 对 \(10^9+7\) 取模后的异或和。

思路:

考虑到 Dirichlet 卷积的性质,以及 \(f(1)=1\),对于 \(f^n\) 一般的处理是:
令 \(f=\varepsilon +h\),则有 \(\displaystyle f^n=(\varepsilon +h)^n=\sum_{i=0}^{n}\binom{n}{i}h^i,(h^0=\varepsilon)\)。
由于 \(h(1)=0\),对于 \(h^n\) 来说,当 \(i<2^n\) 时,\(h^n(i)=0\)。
\(\displaystyle g=\sum_{i=1}^{m}f^i=\sum_{i=1}^{m}\sum_{j=0}^{i}\binom{i}{j}h^j=\sum_{j=0}^{m}h^j\sum_{i=1}^{m}\binom{i}{j}=m*\varepsilon+\sum_{j=1}^{m}h^j\sum_{i=1}^{m}\binom{i}{j}=m*\varepsilon+\sum_{j=1}^{m}h^j\binom{m+1}{j+1}\)
然后直接计算即可,\(h\) 只需计算到 \(h^{20}\) 即可。

代码

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define double long double
#define PII pair<int,int>
using namespace std;
mt19937_64 rng(time(0));

const int N = 1e6 + 10, M = 1e3, mod = 1e9+7;
const double EPS = 1e-8;


int qpow(int x, int n) {
	int ans = 1;
	while (n) {
		if (n & 1) {
			ans *= x;
			ans %= mod;
		}
		x *= x;
		x %= mod;
		n >>= 1;
	}
	return ans;
}
int f[N];
int h[22][N];
//int fac[N];
//int inv[N];
//void init(){
//	fac[0]=inv[0]=1;
//	for(int i=1;i<N;i++){
//		fac[i]=fac[i-1]*i%mod;
//	}
//	inv[N-1]=qpow(fac[N-1],mod-2);
//	for(int i=N-2;i>=0;i--){
//		inv[i]=inv[i+1]*(i+1)%mod;
//	}
//}
//
//
//int C(int n,int m){
//	return fac[n]*inv[m]%mod*inv[n-m]%mod;
//}
int inv2[N];
void solve() {
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>f[i];
		if(i>1){
			h[1][i]=f[i];
		}
	}
	for(int i=1;i<=30;i++){
		inv2[i]=qpow(i,mod-2);
	}
	int ans=0;
	for(int i=2;i<=20;i++){
		for(int j=1;j<=n;j++){
			if(h[i-1][j]==0)continue;
			for(int k=1;k*j<=n;k++){
				h[i][k*j]+=h[1][k]*h[i-1][j]%mod;
				h[i][k*j]%=mod;
			}
		}
	}
	for(int i=1;i<=n;i++){
		int res=0;
		if(i==1){
			res=m;
		}
		int c=m+1;
		for(int j=1;j<=min(m,20ll);j++){
			c*=(m+1-j);
			c%=mod;
			c*=inv2[j+1];
			c%=mod;
			res+=h[j][i]*c;
			res%=mod;
		}
//		cout<<res<<' ';
		ans^=res;
		
	}
	cout<<ans<<endl;


}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t = 1;
//	cin >> t;
//	init();
	while (t--) {
		solve();
	}

	return 0;
}
posted @ 2026-09-23 20:04  ptlks  阅读(12)  评论(0)    收藏  举报