BD202402跑步 线性求逆元 素数筛 数学

思路

参考 橙之夏 小码_205886 题解

  • 设整个过程用时t,第i个人跑 t i t\over i it圈
  • 每个人在整数倍时回到起点,即 t = l c m ( 1 , . . . , n ) = l t=lcm(1,...,n)=l t=lcm(1,...,n)=l时
  • 假设 i < j i<j i<j,两个人差了 t i − t j {t\over i}-{t\over j} it−jt圈,也是相遇的次数

快的人相对于慢的人的速度为 v 1 − v 2 v_1 - v_2 v1−v2,相对路程为 ( v 1 − v 2 ) t (v_1 - v_2)t (v1−v2)t。

每相遇一次,相对路程增加 L L L(1 圈),因此相遇次数为 ( v 1 − v 2 ) t L = v 1 t L − v 2 t L = a − b \frac{(v_1 - v_2)t}{L} = \frac{v_1 t}{L} - \frac{v_2 t}{L} = a - b L(v1−v2)t=Lv1t−Lv2t=a−b。

  • 总招呼数 ∑ i = 1 n ∑ j = i + 1 n ( l i − l j ) \sum_{i=1}^n \sum_{j=i+1}^n({l\over i}-{l\over j}) ∑i=1n∑j=i+1n(il−jl)
  • 公式化简

1 i 1\over i i1使用线性求逆元

cpp 复制代码
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 > 1 i>1 i>1时,设 m / i = k . . . . . . r , k ⋅ i + r ≡ 0 ( m o d m ) m/i=k......r,k\cdot i+r\equiv 0(mod\ m) m/i=k......r,k⋅i+r≡0(mod m)

  • 两边乘 i − 1 r − 1 , k ⋅ r − 1 + i − 1 ≡ 0 ( m o d m ) 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 ( m o d m ) i − 1 ≡ ( m − m i ) ⋅ r − 1 ( m o d m ) 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

cpp 复制代码
//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;
}

代码

cpp 复制代码
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;

}
相关推荐
格林威44 分钟前
常规线扫描镜头有哪些类型?能做什么?
人工智能·深度学习·数码相机·算法·计算机视觉·视觉检测·工业镜头
007php0071 小时前
某大厂跳动面试:计算机网络相关问题解析与总结
java·开发语言·学习·计算机网络·mysql·面试·职场和发展
知识分享小能手1 小时前
微信小程序入门学习教程,从入门到精通,微信小程序核心 API 详解与案例(13)
前端·javascript·学习·react.js·微信小程序·小程序·vue
递归不收敛2 小时前
吴恩达机器学习课程(PyTorch 适配)学习笔记:3.3 推荐系统全面解析
pytorch·学习·机器学习
程序员莫小特3 小时前
老题新解|大整数加法
数据结构·c++·算法
过往入尘土4 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.4 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
又是忙碌的一天4 小时前
前端学习 JavaScript(2)
前端·javascript·学习
蒙奇D索大4 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
玲娜贝儿--努力学习买大鸡腿版4 小时前
推荐算法学习笔记(十九)阿里SIM 模型
笔记·学习·推荐算法