# 题解 I. gcd -“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛(正式赛）

VP 的时候失误推错太多次了，写个博客总结一下

## 【分析】

$$\displaystyle res=\sum_{i, j\geq 1}(m-1)\cdot \dbinom {n-i-j-1} {m-3} \cdot \gcd(i, j)\cdot w(j)$$

$$\displaystyle res=(m-1)\sum_{k=2}^n \dbinom {n-k-1} {m-3} \cdot \sum_{i+j=k}\gcd(i, j)\cdot w(j)$$

$$\displaystyle \sum_{i+j=k}\gcd(i, j)\cdot w(j)=\sum_{j=1}^{k-1} \gcd(k, j)\cdot w(j)=\sum_{j=1}^k \gcd(k, j)\cdot w(j)-k\cdot w(k)$$

$$\displaystyle w(j)=\sum_t c_tj^t$$$$\displaystyle \sum_{j=1}^k\gcd(k, j)\cdot w(j)=\sum_t c_t\sum_{j=1}^k\gcd(k, j)\cdot j^t$$

\begin{aligned} &\sum_{j=1}^k\gcd(k, j)\cdot j^t \\=&\sum_{g\mid k} g \sum_{j=1}^k[\gcd(k, j)=g]\cdot j^t \\=&\sum_{g\mid k} g \sum_{j=1}^{k\over g}[\gcd({k\over g}, j)=1]\cdot (jg)^t \\=&\sum_{g\mid k} g^{t+1} \sum_{j=1}^{k\over g}\sum_{d\mid {k\over g}\wedge d\mid j}\boldsymbol \mu(d)\cdot j^t \\=&\sum_{gd\mid k} g^{t+1}\boldsymbol \mu(d)\sum_{j=1}^{k\over gd} (jd)^t \\=&\sum_{gd\mid k} g^{t+1}\cdot (\boldsymbol \mu(d)\cdot d^t)\cdot \sum_{j=1}^{k\over gd} j^t \\=&\sum_{gdq=k}g^{t+1}\cdot (\boldsymbol \mu(d)\cdot d^t)\cdot S_t(q) \end{aligned}

\begin{aligned} &\sum_{j=1}^k\gcd(k, j)\cdot j^t \\=&\sum_{gdq=k}g^{t+1}\cdot (\boldsymbol \mu(d)\cdot d^t)\cdot S_t(q) \\=&\sum_{gdq=k}g^{t+1}\cdot (\boldsymbol \mu(d)\cdot d^t)\cdot \sum_{i=0}^{t+1}A_{t, i} q^i \\=&\sum_{i=0}^{t+1}A_{t, i} \sum_{gdq=k} g^{t+1}\cdot (\boldsymbol \mu(d)\cdot d^t)\cdot q^i \end{aligned}

\begin{aligned} &\boldsymbol f_{t,i}(p^e) \\=&\sum_{x+y+z=e}(p^x)^{t+1}\cdot (\boldsymbol \mu(p^y)\cdot (p^y)^t)\cdot (p^z)^i \\=&\sum_{x+z=e}(p^x)^{t+1}\cdot (p^z)^i-\sum_{x+z=e-1} (p^x)^{t+1}\cdot (p^z)^i\cdot p^t \\=&p^{ei}\sum_{x=0}^e (p^x)^{t+1-i}-p^{(e-1)i+t}\sum_{x=0}^{e-1}(p^x)^{t+1-i}&(i\leq t+1) \end{aligned}

$$t+1-i>0$$ 时，有：

\begin{aligned} &\boldsymbol f_{t,i}(p^e) \\=&p^{ei}\cdot {1-p^{(e+1)(t+1-i)}\over 1-p^{t+1-i}}-p^{(e-1)i+t}\cdot {1-p^{e(t+1-i)}\over 1-p^{t+1-i}} \\=&{p^{ei}\cdot (1-p^{t-i}) - p^{e(t+1)+t-i}\cdot (p-1)\over 1-p^{t-i+1}} \end{aligned}

$$t+1-i=0$$ 时，有：

\begin{aligned} &\boldsymbol f_{t,i}(p^e) \\=&p^{ei}\cdot (e+1)-p^{ei+t-i}e \end{aligned}

## 【代码】

#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;
}

posted @ 2022-11-25 11:54  JustinRochester  阅读(51)  评论(0编辑  收藏  举报