zoukankan      html  css  js  c++  java
  • Interstellar Hunter【2020CCPC秦皇岛-I】

    题意

    在一个无限大的二维平面内,(Alex) 的起点为 ((0,0)) 。他可以获得若干的数对 ((a,b)) ,使得他可以从点 ((x,y)) 跳跃到 ((x+a,y+b)) 或者 ((x-a,y-b)) ,跳跃的次数不限。同时,会给出若干的点的坐标 ((x,y)),且该点处有 (w) 的能量可以获得。(Alex) 可以选择去获取该点的能量或者忽略它。

    (1leq T leq 10^4,1leq Q leq 10^5,0leq x_i,y_ileq 10^6,1leq w_ileq 10^9)

    题目链接:https://codeforces.com/gym/102769/problem/I

    分析

    对于二维平面的可以到达的点集,可以通过构造两个基向量来表示,即:((X_1,Y_1))((0,Y_2)) ,其中,(Y_2geq0,X_1geq 0,Y1<Y_2)

    假设当前加入的向量为: ((a,b)) ,首先对于合成的新向量的 (X) 部分,(X_1'=gcd(X_1,a)) ,因为 ((0,Y_2)) 不会对 (X) 产生影响。可以使用拓展欧几里得来求解,同时求出各自的系数,便于求出 (Y_1')。接下来,考虑 ((X_1,Y_1))((a,b)) 进行线性组合产生一个向量 ((0,d)) ,那么反过来,通过向量 ((X_1,Y_1))((0,d)) 的线性组合就可以产生向量 ((a,b)) 。因此,我们只需要将 ((0,d))((0,Y_2)) 进行合并即可,显然 (Y_2'=gcd(d,Y_2)) 。那么,该如何合成向量 ((0,d)) 呢?可以发现,只要使得合成后的向量的水平方向为 (0) 即可。那么,(d=(X_1·b-a·Y_1)) ,为了防止数据过大,可以除以 (gcd(X_1,a))

    求出了每次添加新向量之后的新基向量,对于给出的每个点,我们只需要判断是否可以用基向量表示即可。复杂度:(O(nlog(x+y)))

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    void read(int &x)
    {
        x=0;
        int f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<3)+(x<<1)+ch-'0';
            ch=getchar();
        }
        x*=f;
    }
    ll gcd(ll x,ll y)
    {
        return y?gcd(y,x%y):x;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return a;
        }
        ll res=exgcd(b,a%b,x,y);
        ll tmp=x;
        x=y;
        y=tmp-(a/b)*y;
        return res;
    }
    int main()
    {
        int T,q,cnt=0;
        read(T);
        while(T--)
        {
            read(q);
            int op,x,y,w;
            ll u=0,v=0,ans=0;
            ll g,X1=0,Y1=0,Y2=0;
            for(int i=1;i<=q;i++)
            {
                read(op);
                if(op==1)//向量的合成
                {
                    read(x),read(y);
                    g=exgcd(X1,x,u,v);
                    if(g==0) Y2=gcd(Y2,1LL*y);
                    else Y2=gcd(Y2,(x*Y1-y*X1)/g);
                    if(g==0) Y1=y;
                    else Y1=Y1*u+y*v;
                    if(Y2) Y1=(Y1%Y2+Y2)%Y2;
                    X1=g;
                }
                else
                {
                    read(x),read(y),read(w);
                    if(X1==0)//首先满足:x=0
                    {
                        if(x!=0) continue;
                        if(Y1==0)
                        {
                            if(y!=0)
                            {
                                if(Y2!=0&&y%Y2==0)
                                    ans+=w;
                            }
                            else ans+=w;
                        }
                        else
                        {
                            if(Y2==0&&y%Y1==0)
                                ans+=w;
                            else if(Y2!=0)
                            {
                                g=exgcd(Y1,Y2,u,v);
                                if(y%g==0) ans+=w;
                            }
                        }
                    }
                    else
                    {
                        if(x%X1!=0) continue;
                        if(Y2==0)
                        {
                            if(X1*y==x*Y1)
                                ans+=w;
                            continue;
                        }
                        if((y-(x/X1)*Y1)%Y2==0)
                            ans+=w;
                    }
                }
            }
            printf("Case #%d: %lld
    ",++cnt,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    conda安装使用
    数据库删除后台代码
    表格显示数据库(html和php混编)
    唯一用户名jquery和PHP代码
    //阿贾克斯提交数据库
    //向数据库添加数据(form表单提交)
    //conn数据库配置
    Css 变量
    input标签让光标不出现
    Es6Class
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13859375.html
Copyright © 2011-2022 走看看