P10084 [GDKOI2024 提高组] 计算题解

· · 题解

看不清公式可以放大。

题意简单转化

首先有 \gcd(x^{a}-1,x^{b}-1)+1=x^{\gcd(a,b)}

证明:

因为当 a\ge b 时, \gcd(a,b)=\gcd(a-b,b)

让我们钦定 a\ge b,那么

考虑 \gcd(x^{a}-1,x^{b}-1)=\gcd(x^{a}-x^{b},x^{b}-1)=\gcd(x^{b}(x^{a-b}-1),x^{b}-1)

由于 \gcd(x^{b},x^{b}-1)=1,所以

\gcd(x^{b}(x^{a-b}-1),x^{b}-1)=\gcd(x^{a-b}-1,x^{b}-1)

我们发现指数在更相减损!

直到更相减损结束的时候,即 \gcd(x^{\gcd(a,b)}-1,x^{0}-1) 时,我们得到原式为 x^{\gcd(a,b)}-1

发现 m\vert L-1m\vert R,将 L,R 都减去 L,原问题相当于 [1,N] 的问题。

这题中有多项式 f(x)=(1+x)(1+x^{2})(1+x^{3})\cdots (1+x^{k})=c_{0}+c_{1}x+c_{2}x^{2}+\cdots+c_{t}x^{t}

我们知道展开这个多项式,就相当于在每一个括号内选取一项相乘。

因为 $x$ 是任意代入的,所以我们希望代入一些具有优秀性质的 $x$ 来简化我们的运算。 --- 引理 $$ [m\vert i]=\frac{1}{m}\sum_{k=0}^{m-1}\omega_{m}^{ik} $$ 证明: 考虑等比数列求和:$S=\frac{\omega_{m}^{im}-1}{\omega_{m}^{i}-1}$,分类讨论: - 当 $\omega_{m}^{i}\not=1$ 时,可以知道 $i$ 不是 $m$ 的倍数,并且 $\omega_{m}^{im}-1$ 为0。 - 当 $\omega_{m}^{i}=1$ 时,可以知道 $i$ 是 $m$ 的倍数,并且由于分母为0,此时不能使用等比数列求和公式,所以特判。此时 $\omega_{m}^{ik}=1$,因为 $i$ 是 $m$ 的倍数。得到 $\sum_{k=0}^{m-1}\omega_{m}^{ik}=m$,所以除以 $m$ 得到1。 --- 将 $m$ 次单位根代入得到 $\sum f(\omega_{m}^{i})$,展开,由引理得到只有 $m\vert i$ 时,系数为 $c_{i}$ 的项的和不为0。而下标为 $m$ 的倍数的数相加得到 $m\times c_{k}$。故答案为 $$ \frac{1}{m}\sum f(\omega_{m}^{i}) $$ 问题转化为快速计算该式子。 --- 当 $m$ 为奇素数的时候: 考虑:根据单位根的定义,我们可以对 $z^{m}-1$ 在复数域内进行因式分解。得到 $z^{m}-1=(z-\omega_{m}^{0})(z-\omega_{m}^{1})\cdots(z-\omega_{m}^{m-1})$,代入 $z=-1$,进一步得到 $2=(1+\omega_{m}^{1})(1+\omega_{m}^{2})\cdots(1+\omega_{m}^{m})$。又因为 $m$ 是素数,所以 $(1+\omega_{m}^{i})(1+\omega_{m}^{2i})\cdots(1+\omega_{m}^{mi})$ 的指数模 $m$ 组成了一个完全剩余系,其值仍然等于2。 > 当然,如果 $m$ 为偶数的时候,可以得到 $z^{m}=(-1)^{m}=1$,所以该式子等于0。 进一步对其拓展,我们知道 $n$ 是 $m$ 的倍数,那么当 $i>0$ 时, $f(\omega_{m}^{i})=(1+\omega_{m}^{i})(1+\omega_{m}^{2i})\cdots(1+\omega_{m}^{ni})=2^{\frac{n}{m}}$。当 $i=0$ 时,该式等于 $2^{n}$。 所以答案等于 $\frac{1}{m}(2^{n}+(m-1)2^{\frac{n}{m}})$。 --- 拓展到 $m$ 一般的情况,考虑假设$(i,m)=p$,1~m分别乘 i 模 m 得到的剩余系,包含 $\frac{m}{p}$ 个数,是由 $p$ 个 模 $\frac{m}{p}$ 的完全剩余系中的数字乘 $p$ 得到的。 那么可以将 $(1+\omega_{m}^{i})(1+\omega_{m}^{2i})\cdots(1+\omega_{m}^{mi})$ 按照模 $m$ 得到的值可以表示为 $[(1+\omega_{m}^{p})(1+\omega_{m}^{2p})\cdots(1+\omega_{m}^{m})]^{p}$。 所以 $f(\omega_{m}^{i})=[(1+\omega_{m}^{p})(1+\omega_{m}^{2p})\cdots(1+\omega_{m}^{m})]^{p\times \frac{n}{m}}$。 注意到单位根的性质 $\omega_{m}^{p}=\omega_{\frac{m}{p}}^{1}$,所以其实上式中括号内的部分就是 $(1+\omega_{\frac{m}{p}}^{1})(1+\omega_{\frac{m}{p}}^{2})\cdots(1+\omega_{\frac{m}{p}}^{\frac{m}{p}})$。 当 $\frac{m}{p}$ 为偶数的时候,上面的式子为0。当 $\frac{m}{p}$ 为奇数的时候,上面的式子为2。所以 $f(\omega_{m}^{i})=2^{p\times\frac{n}{m}}[2\nmid \frac{m}{p}]$。 所以答案等于 $\frac{1}{m}(2^{n}+\sum_{i=1}^{m-1}2^{\frac{n}{m}\times p}[2\nmid \frac{m}{p}])$。 我们之前特判了 $i=0$ 的情况,其实 $i=0$ 和 $i=m$ 是一样的,当 $i=m$ 时,$p=m$,$2^{\frac{n}{m}\times p}[2\nmid \frac{m}{p}])=2^{n}$,所以式子可以简化为: $$ \frac{1}{m}(\sum_{i=0}^{m-1}2^{\frac{n}{m}\times p}[2\nmid \frac{m}{p}]) $$ 直接计算可以获得 85 分。 --- 进一步优化,观察到如果 $2\vert \frac{m}{(i,m)}$ 时,$i$ 对答案没有贡献。所以假设 $m=2^{k}\times u$,其中 $u$ 是一个奇数,那么 $i$ 要求满足 $i=2^{k}\times x$。 所以有: $$ \begin{aligned} \frac{1}{m}(\sum_{i=0}^{m-1}2^{\frac{n}{m}\times p}[2\nmid \frac{m}{p}])&=\frac{1}{m}(\sum_{i=1}^{u}2^{\frac{n}{2^{k}\times u}\times \gcd(2^{k}\times u,2^{k}\times i)})\\ &=\frac{1}{m}(\sum_{i=1}^{u}2^{\frac{n}{u}\times \gcd(u,i)}) \end{aligned} $$ 考虑到 $\gcd(u,i)$ 为 $u$ 的约数,我们直接枚举 $\gcd(u,i)$,也就是: $$ \frac{1}{m}(\sum_{d\vert u}2^{\frac{n}{u}\times d}\times \varphi(\frac{u}{d})) $$ 因为 $\gcd(u,i)=d$ 要求 $\gcd(\frac{u}{d},\frac{i}{d})=1$,所以有多少个 $\frac{i}{d}$ 满足 $\gcd(\frac{u}{d},\frac{i}{d})=1$ 就是与 $\frac{u}{d}$ 互质的数字的个数。 由于 $u$ 的特殊性(没有质因子2),所以其约数个数不会太多,1e7 之内大约只有 200 个,可以通过本题。 代码: ```c++ #include<cstdio> #include<cmath> using namespace std; using ll=long long; const int mod=998244353; const int M=1e7+5; ll qpow(ll a,ll b){ ll res=1; while(b){ if(b&1)res=res*a%mod; a=a*a%mod; b>>=1; } return res; } ll qpowNoMod(ll a,ll b){ ll res=1; while(b){ if(b&1)res=res*a; a=a*a; b>>=1; } return res; } int phi[M],pri[M],tot; bool vis[M]; void init(){ phi[1]=1; for(int i=2;i<=(int)1e7;++i){ if(!vis[i])phi[i]=i-1,pri[++tot]=i; for(int j=1;j<=tot;++j){ if(pri[j]*i>1e7)break; vis[pri[j]*i]=true; if(i%pri[j]==0){phi[pri[j]*i]=phi[i]*pri[j];break;} phi[pri[j]*i]=phi[i]*(pri[j]-1); } } } int gcd(int x,int y){ return y==0?x:gcd(y,x%y); } ll F(int m,int x,int y){ if(x==0||y==0)return 0; return qpowNoMod(m,gcd(x,y)); } int main(){ init(); int t; scanf("%d",&t); while(t--){ int m,a,b,c,d; scanf("%d%d%d%d%d",&m,&a,&b,&c,&d); ll l=F(m,a,b)+1,r=F(m,c,d); ll n=r-l+1; int u=m; while(!(u&1))u>>=1; ll ans=0; for(int i=1,_i=sqrt(u+0.5);i<=_i;++i){ if(u%i!=0)continue; ans+=qpow(2,n/u*i)*phi[u/i]%mod; if(i*i!=u){ int j=u/i; ans+=qpow(2,n/u*j)*phi[u/j]%mod; ans%=mod; } } ans*=qpow(m,mod-2); ans%=mod; printf("%lld\n",ans); } } ```