• Gym102769I Interstellar Hunter 题解


    Gym102769I Interstellar Hunter 题解

    题意:初始位置在 ((0,0)) 点,现在有两种操作:

    • 操作 (1) :你获得一种能力向量 ((x,y)) ,你可以从当前位置 ((a,b)) 出发,沿着这个能力向量方向移动任意整数个单位,即可以从 ((a,b)) 移动至 ((a+dx,b+dy))
    • 操作 (2) :在二维平面上的某一点 ((x,y)) 上出现了一个价值为 (w) 的物品,如果你可以通过你当前拥有的能力向量移动至 ((x,y)) 就可以获得该物品。

    问最终你可以获得的最大价值是多少?

    题解:本题的核心思想是对于一系列的能力向量 ((x_0,y_0),(x_1,y_1),(x_2,y_2),cdots) 的线性组合,我们都可以通过两个基向量 ((bx,by))((dx,0)) 的线性组合来得到,比较详细的证明请参考出题人在这个问题下的回答:

    https://www.zhihu.com/question/426081900/answer/1535613903

    因此我们需要维护这组基向量,使它能够表示所有能力向量的线性组合。

    假设某一时刻,我们的基向量是 ((bx,by))((dx,0)) ,现在加入了一个新的能力向量 ((x,y)) ,我们需要求解出新的基向量 ((bx',by'))((dx',0)) 。首先容易求得 (by'=gcd(by,y)) ,然后考虑 (dx') ,利用 ((bx,by))((x,y)) 线性组合得到它们在 (x) 轴上的基向量:

    [egin{aligned} frac{y}{g}(bx,by)-frac{by}{g}(x,y)=(frac{1}{g}(ycdot bx-bycdot x),0) end{aligned} ]

    再和原先的基向量 ((dx,0)) 组合就能得出 (dx'=gcd(dx,frac{|ycdot bx - bycdot x|}{g}))

    最后,我们通过 (exgcd) 求出 (bx') :由裴蜀定理可以得出,存在 (a,bin Z) 使得 (acdot y+bcdot by=gcd(y,by)) ,因此我们可以通过 (exgcd) 求解该方程的一组解 ((a,b)) 并得到:(bx'=(acdot x+bcdot bx)mod{dx'})

    于是,我们就得到了一组新的基向量 ((bx',by'))((dx',0)) ,最后注意一下向量某一维为零的特殊情况即可。

    #include <bits/stdc++.h>
    using namespace std;
     
    template<typename T>
    T exgcd(T x, T y, T& a, T& b) {
    	if (!y) {
    		a = 1, b = 0;
    		return x;
    	}
    	T d = exgcd(y, x % y, b, a);
    	b -= x / y * a;
    	return d;
    }
     
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	cout.tie(nullptr);
    	int t; cin >> t;
    	for (int kase = 1; kase <= t; kase++) {
    		int n; cin >> n;
    		long long ans = 0;
    		long long bx = 0, by = 0, dx = 0;
    		for (int i = 0; i < n; i++) {
    			int op; cin >> op;
    			long long x, y, w;
    			if (op == 1) {
    				long long a, b;
    				cin >> x >> y;
    				long long g = exgcd(y, by, a, b);
    				dx = __gcd(dx, abs(y * bx - x * by) / g);
    				by = g;
    				bx = a * x + b * bx;
    				if (dx) {
    					bx = (bx % dx + dx) % dx;
    				}
    			}
    			else {
    				cin >> x >> y >> w;
    				if (by && y % by == 0) {
    					long long r = x - y / by * bx;
    					if (dx && r % dx == 0 || dx == r) {
    						ans += w;
    					}
    				}
    				else if (by == 0) {
    					if (bx && x % bx == 0 || bx == x) {
    						ans += w;
    					}
    				}
    			}
    		}
    		cout << "Case #" << kase << ": " << ans << '
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    java实现第六届蓝桥杯灾后重建
    java实现第六届蓝桥杯打印菱形
    java实现第六届蓝桥杯打印菱形
    java实现第六届蓝桥杯九数分三组
    java实现第六届蓝桥杯九数分三组
    java实现第六届蓝桥杯打印菱形
    java实现第六届蓝桥杯九数分三组
    java实现第六届蓝桥杯九数分三组
    java实现第六届蓝桥杯九数分三组
    java实现第六届蓝桥杯打印菱形
  • 原文地址:https://www.cnblogs.com/st1vdy/p/13870452.html
Copyright © 2020-2023  润新知