• 【洛谷】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....

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

    ↘         ↓          ↙

    →    传送门     ←

    ↗         ↑          ↖

    (完)

  • 相关阅读:
    AcWing 1135. 新年好 图论 枚举
    uva 10196 将军 模拟
    LeetCode 120. 三角形最小路径和 dp
    LeetCode 350. 两个数组的交集 II 哈希
    LeetCode 174. 地下城游戏 dp
    LeetCode 面试题 16.11.. 跳水板 模拟
    LeetCode 112. 路径总和 递归 树的遍历
    AcWing 1129. 热浪 spfa
    Thymeleaf Javascript 取值
    Thymeleaf Javascript 取值
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11341198.html
Copyright © 2020-2023  润新知