zoukankan      html  css  js  c++  java
  • 【洛谷】P2371 [国家集训队]墨墨的等式(屠版题)

    先讲讲曲折的思路吧......

    首先,应该是CRT之类的东西,乱搞

    不行......打了打草稿,发现有解的情况是gcd(a1,a2.....an)|B,于是可以求gcd然后O(n)查询?但是B的范围直接劝退...

    (这是cyr大佬讲的“烂大街”的套路(来自ctsc哦))于是我翻开了课件和百度

    课件:最短路乱搞 百度:同余最短路???

    说白了还是数论喽???

    题解:

     在课件和草稿纸的帮助下,我成功地推出了一个结论:

    对于最后一个a,也就是an,设anxn=q,假设前面的数加起来是S,则S+q=B;

    对于不同的Xn,q总是一个等差数列。

    所以:(B-S)%an=0;

    ∴B %an=S%an.(B>S)

    所以发现:如果式子可以达到S+q,那么式子一定也能达到S+(i*q)。

    所以我们的任务就是求对于每一个a的最小S。

    怎么求呢?

    首先找出ai中的最小值mn

    因为要求剩余系嘛,剩余我们可以连边,在i与(a[i]+i)%mn之间连一条权值为a[i]的单向边,表示在mod mn=i到mod mn=(i+ai)%mn之间,可以通过a[j]的代价达到,于是这样就处理出了每一个点的最小剩余系

    于是,对于每一个S,答案就是Σ(dis[i]<a[j])(a[i]-dis[i])/mn+1

    于是,这题的代码就没有什么含金量了(虽然我调了整整一上午+1h,而且整整屠了一个半的版)

    坑点1:会爆long long

    坑点2:无脑开long long会MLE

    坑点3、long long 和int不能乱用

    代码1(跑得快的)(因为没有邻接表,直接从前面一个点得出下面一个点)

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=5e6+6;
    const int maxm=5e5+5;
    const ll inf=1e12+1;
    int n;
    int tot;
    ll l,r;
    int mn=maxm+5;
    int a[maxm];
    int cnt,head[maxm];
    inline  ll read()
    {
        ll f=1,x=0;char s=getchar();
        while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
        while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    struct edge
    {
        int to,next,dis;
    }e[maxn];
    inline void addedge(int from,int to,int dis)
    {
        e[++cnt].next=head[from];
        e[cnt].to=to;
        e[cnt].dis=dis;
        head[from]=cnt;
    }
    ll dis[maxn];
    int vis[maxn];
    struct cmp
    {
        bool operator() (int a,int b)
        {
            return dis[a]>dis[b];
        }
    };
    //queue < int > q;
    priority_queue < int , vector < int > , cmp > q;
    void spfa(int s)
    {
        memset(dis,0x3f,sizeof(dis));
        q.push(s);
        dis[s]=0;
        vis[s]=1;
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            vis[u]=0;
            for(int i=1;i<=n;i++)
            {
                int v=(u+a[i])%mn;
                if(dis[v]>dis[u]+a[i])
                {
                    dis[v]=dis[u]+a[i];
                    if(vis[v]==0)
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    ll query(ll x)
    {
        ll res=0;
        for(int i=0;i<=mn;i++)
        {
            if(dis[i]<=x)
            {
                res+=(x-dis[i])/mn+1;
            }
        }
        return res;
    }
    int main()
    {
        n=read();l=read();r=read();//
        for(int i=1;i<=n;i++)
        {
            ll x;
            x=read();
            if(x==0)
            continue;
            a[++tot]=x;
            mn=min(mn,a[i]);
    
        }
        /*for(ll i=0;i<=mn;i++)
        {
            for(int j=1;j<=tot;j++)
            {
                if(a[j]!=mn)
                addedge(i,(i+a[j])%mn,a[j]);
            }
        }*/
        spfa(0);
        printf("%lld",query(r)-query(l-1));
        return 0;
    }

    代码2:(跑得慢的)

    把上面魔改一下就行了233....

    慢着!你以为到这就结束了?

    ↘         ↓          ↙

    →    传送门     ←

    ↗         ↑          ↖

    (完)

  • 相关阅读:
    HDU 1042 N!
    linux上安装wps办公软件
    《UNIX环境高级编程》笔记--环境变量
    【StatLearn】统计学习中knn算法实验(2)
    Asp.Net验证控件浅析
    斜率小于0的连线数量-归并排序
    Printk与sched_clock_init的一点分析
    【数字图像处理】使用kmeans算法对TrueColor图片进行优化
    将 Shiro 作为应用的权限基础 三:基于注解实现的授权认证过程
    python中os/sys/platform模块区别
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11341198.html
Copyright © 2011-2022 走看看