EXCRT求捞
查看原帖
EXCRT求捞
324412
Filberte楼主2023/11/17 08:20

15 opts,本地样例有一个输出了负数,怀疑是哪里long long 溢出了(但是检查了很多次,应该开 __int128的地方都开了)

#include <bits/stdc++.h>
#define int long long
#define LL __int128
using namespace std;
const int N = 1e5 + 100;
int n, k, ned;
int m[N], nw[N], r[N], c[N];
// c[i] · x = r[i] (mod m[i])
void exgcd(int a , int b , int &g , int &x , int &y){
    if(!b){g = a , x = 1 , y = 0;return ;}
    exgcd(b , a % b , g , y , x);
    y -= a / b * x;
}
pair<int, int> merge(int r1, int m1, int r2, int m2){
	int p, q, g; 
	exgcd(m1, m2, g, p, q);
	if((r2 - r1) % g) return make_pair(-1, -1);
	int t = m2 / g;
    p = (LL)(p * ((r2 - r1) / g)) % t;
	pair<int, int> ret = make_pair(m1 * p + r1, m1 * t);
	ret.first = (ret.first % ret.second + ret.second) % ret.second;
	return ret;
}
int inv(int a, int p){
	int x, y, g;
	exgcd(a, p, g, x, y);
	if(g != 1) return -1;
	return x;
}
int find(int x, int mn, int p){int ex = mn / p * p + x;if(ex < mn) ex += x;return ex;}
int excrt(){
	int iv, m1, r1;
	iv = inv(c[1], m[1]);
	if(iv == -1) return -1;
	r1 = (LL)iv * r[1] % m[1], m1 = m[1];
	for(int i = 2;i <= n;i++){
		iv = inv(c[i], m[i]);
		if(iv == -1) return -1;
		pair<int, int> u = merge(r1, m1, (LL)iv * r[i] % m[i], m[i]);
		if(u.first == -1) return -1;
		r1 = u.first, m1 = u.second;
	}
	return find(r1, ned, m1);
}
int fl(int x, int y){return (x - 1) / y + 1;}
signed main(){
	freopen("in.txt","r",stdin);
	int cas;scanf("%lld",&cas);while(cas--){
		ned = 0;
        multiset <int> st;
		assert(st.empty());
		scanf("%lld%lld",&n,&k);
		for(int i = 1;i <= n;i++) scanf("%lld",&r[i]);
		for(int i = 1;i <= n;i++) scanf("%lld",&m[i]);
		for(int i = 1;i <= n;i++) scanf("%lld",&nw[i]);
		for(int i = 1, x;i <= k;i++){
            scanf("%lld", &x);
			st.insert(x);
        }
		for(int i = 1;i <= n;i++){
			auto u = st.upper_bound(r[i]);
			if(u != st.begin()) u--;
			c[i] = *u;
			ned = max(ned, fl(r[i], c[i]));
			r[i] = r[i] % m[i];
			st.erase(u), st.insert(nw[i]);
		}
		printf("%lld\n",excrt());
	}
}

2023/11/17 08:20
加载中...