zoukankan      html  css  js  c++  java
  • 「NOI2018」屠龙勇士(CRT)

    /*
    首先杀每条龙用到的刀是能够确定的, 然后我们便得到了许多形如 ai - x * atki | pi的方程
    而且限制了x的最小值
    
    那么exgcd解出来就好了
    
    之后就是扩展crt合并了 
    
    因为全T调了一个小时 结果是没加文件?? 
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<iostream>
    #define ll long long 
    #define M 100010
    #define mmp make_pair
    using namespace std;
    ll read()
    {
    	ll nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    ll n, q, a[M], m[M], p[M], g[M], atk[M], tp, maxx;
    multiset<ll> st;
    ll mul(ll a, ll b, ll mod)
    {
    	b = (b % mod + mod) % mod;
    	ll ans = 0, tmp = a;
    	for(; b; b >>= 1, tmp = (tmp + tmp) % mod) if(b & 1) ans = (ans + tmp) % mod;
    	return ans;
    }
    ll gcd(ll a, ll b)
    {
    	return !b ? a : gcd(b, a % b);
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y)
    {
    	if(!b)
    	{
    		x = 1, y = 0;
    		return a;
    	}
    	else
    	{
    		ll d = exgcd(b, a % b, x, y);
    		ll tmp = x;
    		x = y, y = tmp - a / b * y;
    		return d;
    	}
    }
    
    ll inv(ll a, ll p)
    {
    	ll x, y;
    	ll d = exgcd(a, p, x, y);
    	if(d != 1) return -1;
    	return (x % p + p) % p;
    }
    
    void init()
    {
    	st.clear();
    	tp = maxx = 0;
    	n = read(), q = read();
    	for(int i = 1; i <= n; i++) a[i] = read();
    	for(int i = 1; i <= n; i++) p[i] = read();
    	for(int i = 1; i <= n; i++) g[i] = read();
    	for(int i = 1; i <= q; i++) st.insert(read());
    	for(int i = 1; i <= n; i++)
    	{
    		multiset<ll>::iterator it = st.upper_bound(a[i]);
    		if(it != st.begin()) it--;
    		atk[i] = *it;
    		st.erase(it);
    		st.insert(g[i]);
    	}
    }
    
    ll excrt()
    {
    	ll a1 = a[1], m1 = m[1], a2, m2;
    	if(tp == 0)
    	{
    		a1 = 0;
    	}
    	else
    	{
    		for(int i = 2; i <= tp; i++)
    		{
    			a2 = a[i], m2 = m[i];
    			ll d = gcd(m1, m2);
    			ll c = a2 - a1;
    			if(c % d) return -1;
    			ll k = inv(m1 / d, m2 / d);
    			m2 = m1 / d * m2;
    			a1 = mul(mul(m1 / d, c, m2), k, m2) + a1;
    			a1 %= m2;
    			m1 = m2;
    		}
    	}
    	return max(a1, maxx);
    }	
    
    void cz(int i)
    {
    	// a[i] - x * atk[i] + k * pi = 0
    	// a[i] = x * atk[i] - k * p[i]
    	// x * atk[i] = a[i]    mod p[i]
    	//先处理gcd, 然后处理逆元
    	if(p[i] == 1)
    	{
    		maxx = max(maxx, (a[i] + atk[i] - 1) / atk[i]);
    	}
    	else
    	{
    		tp++;
    		ll gcdd = gcd(atk[i], p[i]);
    		if(a[i] % gcdd)
    		{
    			a[tp] = -1;
    		}
    		else
    		{
    			atk[i] /= gcdd, p[i] /= gcdd;
    			a[i] /= gcdd;
    			a[tp] = mul(a[i], inv(atk[i], p[i]), p[i]);
    			m[tp] = p[i];
    		}
    	}
    }
    
    void work()
    {
    	for(int i = 1; i <= n; i++)
    	{
    		cz(i);
    		if(a[tp] == -1)
    		{
    			puts("-1");
    			return;
    		}
    	}
    	cout << excrt() << "
    "; 
    } 
    
    int main()
    {
    	freopen("dragon.in", "r", stdin);
    	freopen("dragon.out", "w", stdout); 
    	//freopen("dragon1.in", "r", stdin);
    	int t = read();
    	while(t--)
    	{
    		init();
    		work();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    P2676 超级书架
    P2955 [USACO09OCT]奇数偶数Even? Odd?
    P1554 梦中的统计
    P2614 计算器弹琴
    4246 奶牛的身高
    Render2
    @viewChild
    querySelector
    ionic4封装样式原理
    事件委托和事件冒泡
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10674789.html
Copyright © 2011-2022 走看看