题解 I. gcd -“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛(正式赛)
VP 的时候失误推错太多次了,写个博客总结一下
【大意】
求所有长度为 且和为 的正整数序列 的贡献和。其中,每个数列的贡献为
【分析】
考虑从 个位置中,选择两个相邻的位置分别填写 ,则方案数为
剩余的 个正整数的和为 ,则等价于模型“ 个小球放入 个盒子里,要求盒子非空”。由隔板法,方案数为
因此,选中的两个位置分别填写 后,对答案的贡献为
我们只需要枚举正整数 即可:
注意到公式中重复出线的 项,我们可以直接枚举 :
考虑 ,因此有:
因此,现在仅需要求解 即可求得答案
而 有
于是问题简化为如何求解
对于代求式子,我们枚举其 gcd ,并莫比乌斯反演,得到:
其中 , 是自然数 次幂和的第 项系数
代入得到:
最后这个求和项 是积性函数 的迪利克雷卷积,显然也是积性函数
不妨记上述积性函数为 ,则有:
故 时,有:
时,有:
这种式子显然可以欧拉筛:
对于某个质数 ,直接算出它所有幂次的值,然后欧拉筛过程中额外维护最小质因数出线的次数。转移的时候直接查表就行。
复杂度为原欧拉筛复杂度 ,加上处理质数幂次位置的结果。经一些不严谨的半猜半分析,后半部分的复杂度应该也是 。
由于题目所给的式子仅有 ~ 次项,因此我们只要预处理 的 即可筛出所有答案
考虑到
因此,仅需要处理 共 项即可
【代码】
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Lim=1e7, MAXN=Lim+10, P=1e9+7;
inline int kpow(int a, int x) { int ans=1; for(; x; x>>=1, a=(ll)a*a%P) if(x&1) ans=(ll)ans*a%P; return ans; }
inline int inv(int a) { return kpow(a, P-2); }
inline int norm(int v) { return v>=P?v-P:v; }
struct Z {
int v;
inline Z(int v_=0):v(norm(v_)) {}
inline Z& operator += (const Z& x) { v=norm(v+x.v); return *this; }
inline Z& operator -= (const Z& x) { v=norm(v+P-x.v); return *this; }
inline Z& operator *= (const Z& x) { v=(ll)v*x.v%P; return *this; }
inline Z operator + (const Z& x) const { Z y=*this; return y+=x; }
inline Z operator - (const Z& x) const { Z y=*this; return y-=x; }
inline Z operator * (const Z& x) const { Z y=*this; return y*=x; }
inline Z operator ! () const { return inv(v); }
inline operator int() const { return v; }
};
const int SIZ=8;
struct multi_F : public array<Z, SIZ> {
inline multi_F() { fill(0); }
inline multi_F& operator += (const multi_F &x) {
for(int i=0; i<SIZ; ++i) at(i)+=x[i];
return *this;
}
inline multi_F& operator -= (const multi_F &x) {
for(int i=0; i<SIZ; ++i) at(i)-=x[i];
return *this;
}
inline multi_F& operator *= (const multi_F &x) {
for(int i=0; i<SIZ; ++i) at(i)*=x[i];
return *this;
}
inline multi_F operator + (const multi_F &x) const { multi_F y=*this; return y+=x; }
inline multi_F operator - (const multi_F &x) const { multi_F y=*this; return y-=x; }
inline multi_F operator * (const multi_F &x) const { multi_F y=*this; return y*=x; }
};
inline multi_F f(int p, int k, ll pk, multi_F lst) {
static int t[] = {1, 1, 2, 2, 2, 3, 3, 3};
static int i[] = {1, 2, 1, 2, 3, 2, 3, 4};
for(int j=0; j<SIZ; ++j) {
int dif = t[j] + 1 - i[j];
int a = kpow(p, dif+P-2);
if(dif) {
int b = (kpow(pk, i[j]) * (1ll-a) - kpow(pk, t[j]+1) * (p-1ll)%P* a)%P;
lst[j] = (ll)b * inv(1-(ll)a*p%P)%P + P;
}
else
lst[j] = kpow(pk, i[j]) * (k + 1ll - (ll)a*k%P) %P+P;
}
return lst;
}
int minp[MAXN], fr[MAXN], prime[MAXN/10], cntprime;
multi_F fi[MAXN];
inline void sieve() {
fi[1].fill(1);
for(int i=2; i<=Lim; ++i) {
if(!minp[i]) {
prime[++cntprime]=i;
multi_F val=fi[1];
for(ll pk=i, k=1; pk<=Lim; pk*=i, ++k) {
fi[pk]=val=f(i, k, pk, val);
minp[pk]=i;
fr[pk]=1;
}
}
for(int j=1; j<=cntprime; ++j) {
int x=i*prime[j];
if(prime[j] > minp[i] || x>Lim) break;
minp[x]=prime[j];
if(prime[j]==minp[i]) fr[x]=fr[i];
else fr[x]=i;
fi[x]=fi[fr[x]]*fi[x/fr[x]];
}
}
}
int n, m, p, q, r;
Z fact[MAXN], inft[MAXN];
inline Z C(int n, int m) { return m<0||m>n?Z(0):fact[n]*inft[m]*inft[n-m]; }
Z h[MAXN];
inline void init() {
sieve();
cin>>n>>m;
cin>>p>>q>>r;
Z rr=Z(r)*!Z(2);
Z qq=Z(q)*!Z(6);
Z pp=Z(p)*!Z(4);
for(int i=1; i<=Lim; ++i) {
Z g1 = (fi[i][0]*Z(1) + fi[i][1]*Z(1)) * rr;
Z g2 = (fi[i][2]*Z(1) + fi[i][3]*Z(3) + fi[i][4]*Z(2)) * qq;
Z g3 = (fi[i][5]*Z(1) + fi[i][6]*Z(2) + fi[i][7]*Z(1)) * pp;
h[i]=g1+g2+g3;
}
fact[0]=1;
for(int i=1; i<=Lim; ++i) fact[i]=fact[i-1]*Z(i);
inft[Lim]=!fact[Lim];
for(int i=Lim; i; --i) inft[i-1]=inft[i]*Z(i);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
init();
Z res=0;
for(int k=2; k<n; ++k) {
Z tmp=((Z(p)*Z(k)+Z(q))*Z(k)+Z(r))*Z(k)*Z(k);
res+=C(n-k-1, m-3)*(h[k]-tmp);
}
res*=Z(m-1);
cout<<res;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话