zoukankan      html  css  js  c++  java
  • [BZOJ 2118] 墨墨的等式

    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=2118

    [算法]

             首先找出Min{Ai} 

             对于0 - Min{Ai} - 1分别建一个点 , 分别表示一个同余类

             若(i + Aj) % Min{Ai} = k , 则i向k连一条权值为Aj的边

             从0号点开始单源最短路 , 那么就得到了模Min{Ai}为任意数的最小值 

             计算较为简单 , 不再赘述

             时间复杂度 : O(Min{Ai}logMin{Ai}) (需要使用高效的Dijkstra + 堆优化算法)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 13;
    const int MAXA = 5e5 + 10;
    typedef long long LL;
    const LL inf = 1e18;
    
    struct edge
    {
            int to , w , nxt;
    } e[MAXN * MAXA];
    
    int n , mn , tot;
    LL Bmin , Bmax;
    int a[MAXN] , head[MAXA];
    bool visited[MAXA];
    LL dist[MAXA];
    priority_queue< pair<LL , int> , vector< pair<LL , int> > , greater< pair<LL , int> > > q; 
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v , int w)
    {
            ++tot;
            e[tot] = (edge){v , w , head[u]};
            head[u] = tot;
    }
    inline LL calc(LL x , LL y , LL z)
    {
            LL ret = x / y;
            if (x % y >= z && x >= 1) ++ret;
            return ret;        
    }
    
    int main()
    {
            
            read(n); read(Bmin); read(Bmax);
            for (int i = 1; i <= n; i++) read(a[i]);
            mn = a[1];
            for (int i = 2; i <= n; i++)
                    if (a[i] < mn) mn = a[i];
            for (int i = 0; i < mn; i++) 
            {
                    for (int j = 1; j <= n; j++)
                    {
                            addedge(i , (i + a[j]) % mn , a[j]);        
                    }        
            }
            for (int i = 0; i < mn; i++) dist[i] = inf;
            dist[0] = 0;
            q.push(make_pair(0 , 0));
            while (!q.empty())
            {
                    int cur = q.top().second;
                    q.pop();
                    if (visited[cur]) continue;
                    visited[cur] = true;
                    for (int i = head[cur]; i; i = e[i].nxt)
                    {
                            int v = e[i].to , w = e[i].w;
                            if (dist[cur] + w < dist[v])
                            {
                                    dist[v] = dist[cur] + w;
                                    q.push(make_pair(dist[v] , v));
                            }     
                    }        
            }
            LL ans = 0;
            for (int i = 0; i < mn; i++)
            {
                    LL l = max(dist[i] , Bmin) , r = Bmax;
                    if (l > r) continue;
                    ans += calc(r , mn , i) - calc(l - 1 , mn , i);    
            }
            printf("%lld
    " , ans);
            
            return 0;
        
    }
  • 相关阅读:
    【中山纪念中学六年级模拟赛】方格翻转 题解
    高斯消元
    net 控件开发资料
    使用自定义验证组件库扩展 Windows 窗体
    POJ 3032
    UVa 10878 Decode the tape
    C语言I博客作业03
    第十周助教总结
    第十二周助教总结
    C语言I博客作业06
  • 原文地址:https://www.cnblogs.com/evenbao/p/9901896.html
Copyright © 2011-2022 走看看