BD202402跑步 线性求逆元 素数筛 数学
思路
参考 橙之夏 小码_205886 题解
- 设整个过程用时t,第i个人跑tit\over iit圈
- 每个人在整数倍时回到起点,即t=lcm(1,...,n)=lt=lcm(1,...,n)=lt=lcm(1,...,n)=l时
- 假设i<ji<ji<j,两个人差了ti−tj{t\over i}-{t\over j}it−jt圈,也是相遇的次数
快的人相对于慢的人的速度为v1−v2v_1 - v_2v1−v2,相对路程为(v1−v2)t(v_1 - v_2)t(v1−v2)t。
每相遇一次,相对路程增加LLL(1 圈),因此相遇次数为(v1−v2)tL=v1tL−v2tL=a−b\frac{(v_1 - v_2)t}{L} = \frac{v_1 t}{L} - \frac{v_2 t}{L} = a - bL(v1−v2)t=Lv1t−Lv2t=a−b。
- 总招呼数∑i=1n∑j=i+1n(li−lj)\sum_{i=1}^n \sum_{j=i+1}^n({l\over i}-{l\over j})∑i=1n∑j=i+1n(il−jl)
- 公式化简

1i1\over ii1使用线性求逆元
void init(int n){//求线性逆元//递推法inv[1]=1;forr(i,2,n){inv[i]=(M-M/i)*inv[M%i]%M;}//利用阶乘求// fact[0]=1;// forr(i,1,n)fact[i]=1LL*fact[i-1]*i%M;// ifac[n]=qpow(fact[n]);// reforr(i,0,n-1)ifac[i]=1LL*ifac[i+1]*(i+1)%M;// forr(i,1,n)inv[i]=1LL*fact[i-1]*ifac[i]%M;
}
递推法推导
模m意义下,i>1i>1i>1时,设m/i=k......r,k⋅i+r≡0(modm)m/i=k......r,k\cdot i+r\equiv 0(mod\ m)m/i=k......r,k⋅i+r≡0(mod m)
- 两边乘i−1r−1,k⋅r−1+i−1≡0(modm)i^{-1}r^{-1},k\cdot r^{-1}+i^{-1}\equiv 0(mod\ m)i−1r−1,k⋅r−1+i−1≡0(mod m)
- 移项i−1≡−k⋅r−1(modm)i−1≡(m−mi)⋅r−1(modm)i^{-1}\equiv -k\cdot r^{-1}(mod\ m) \\i^{-1}\equiv (m-{m\over i}) \cdot r^{-1}(mod\ m)i−1≡−k⋅r−1(mod m)i−1≡(m−im)⋅r−1(mod m)
质因子分解求lcm

//p[]是素数数组
int L=1;
forr(i,0,p.size()-1){//LCM(1,...,n)int c=0,tp=1;while (tp*p[i]<=n)tp*=p[i],c++;L=1LL*L*qpow(p[i],c)%M;
}
代码
const int N=1e7+10,M=998244353;
int fact[N],ifac[N],vis[N],inv[N];
vector<int>p;
//不会就学
int qpow(int x,int p=M-2,int mul=1)
{for (;p;p>>=1,x=1LL*x*x%M) if (p&1) mul=1LL*mul*x%M; return mul;
}
void init(int n){//求线性逆元inv[1]=1;forr(i,2,n){inv[i]=(M-M/i)*inv[M%i]%M;}//利用阶乘求// fact[0]=1;// forr(i,1,n)fact[i]=1LL*fact[i-1]*i%M;// ifac[n]=qpow(fact[n]);// reforr(i,0,n-1)ifac[i]=1LL*ifac[i+1]*(i+1)%M;// forr(i,1,n)inv[i]=1LL*fact[i-1]*ifac[i]%M;
}
void pfind(int n){vis[1]=vis[0]=1;forr(i,2,n){if(!vis[i]){p.push_back(i);}if(!p.empty())for(auto j:p){if(i*j>n)break;vis[i*j]=1;if(i%j==0)break;}}
}
void solve(){int n;cin>>n;init(n);int ans=0;forr(i,1,n){//(n-2i+1)*1/i// ans+=1LL*((n-2*i+1+M)%M)*inv[i]%M;//运算顺序错误 应该先乘再取模(ans+=1LL*inv[i]*(n-2*i+1+M)%M)%=M;}pfind(n);int L=1;forr(i,0,p.size()-1){//LCM(1,...,n)int c=0,tp=1;while (tp*p[i]<=n)tp*=p[i],c++;L=1LL*L*qpow(p[i],c)%M;}cout<<1LL*L*ans%M<<endl;}
