• bzoj 2118 墨墨的等式


    墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。

    Input

    输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。输入的第二行包含N个整数,即数列{an}的值。

    Output

    输出一个整数,表示有多少b可以使等式存在非负整数解。

    Sample Input

    2 5 10
    3 5

    Sample Output

    5

    Hint

    对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。


      直接说正解,找到ai中的一个数(通常找最小的那一个,这样可以降低时间复杂度,至于为什么,看完应该就知道了),暂且设它为m吧。

      我们知道如果存在一个x,它能够被凑出来,那么(x + m), (x + 2m), ...都可以被凑出来。现在我们要找到这么一个最小的x。先建立一些点0,1,2,...,m - 1,表示满足条件的B模m的值。暂时先不考虑如何求出一次Bmin ~ Bmax中满足条件的B,因为可以用0到Bmax中的方案数减去0到Bmin - 1中的方案数。每个点连n - 1条边,第i个点的第j条边连向第(i + aj) % m个点,边权为aj

      看似有些跑题了,现在来讲讲它在题目中的含义。现在我们希望求到所有满足条件的最小的x,我们知道,当B模m的值为0时,B最小为0。同时我们可以用这个推出与它相邻的点代表的最小的B。再仔细想想,多推一下,这不是等价于求最短路吗?也就是说,从节点0出发,到达i的距离表示,最小的B模m的值为i的B的值。

      最后计算一下方案数(相信你会做)就好了。还有特殊处理当某个a等于0的时候,不然会整数被零除,然后无限RE。另外,贡献一发wa,建图注意是单向的,减个aj就不知道是不是满足了,笑。

    Code

      1 /**
      2  * bzoj
      3  * Problem#2118
      4  * Accepted
      5  * Time:2888ms
      6  * Memory:93712k
      7  */
      8 #include<iostream>
      9 #include<fstream> 
     10 #include<sstream>
     11 #include<algorithm>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<cctype>
     16 #include<cmath>
     17 #include<ctime>
     18 #include<map>
     19 #include<stack>
     20 #include<set>
     21 #include<queue>
     22 #include<vector>
     23 #ifndef WIN32
     24 #define AUTO "%lld"
     25 #else
     26 #define AUTO "%I64d"
     27 #endif
     28 using namespace std;
     29 typedef bool boolean;
     30 #define inf 0xfffffff
     31 #define smin(a, b) (a) = min((a), (b))
     32 #define smax(a, b) (a) = max((a), (b))
     33 template<typename T>
     34 inline boolean readInteger(T& u) {
     35     char x;
     36     int aFlag = 1;
     37     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     38     if(x == -1)    {
     39         ungetc(x, stdin);
     40         return false;
     41     }
     42     if(x == '-') {
     43         aFlag = -1;
     44         x = getchar();
     45     }
     46     for(u = x - '0'; isdigit((x = getchar())); u = u * 10 + x - '0');
     47     u *= aFlag;
     48     ungetc(x, stdin);
     49     return true;
     50 }
     51 
     52 ///map template starts
     53 typedef class Edge{
     54     public:
     55         int end;
     56         int next;
     57         int w;
     58         Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w) {    }
     59 }Edge;
     60 
     61 typedef class MapManager{
     62     public:
     63         int ce;
     64         int *h;
     65         Edge *edge;
     66         MapManager() {    }
     67         MapManager(int points, int limit):ce(0) {
     68             h = new int[(const int)(points + 1)];
     69             edge = new Edge[(const int)(limit + 1)];
     70             memset(h, 0, sizeof(int) * (points + 1));
     71         }
     72         inline void addEdge(int from, int end, int w) {
     73             edge[++ce] = Edge(end, h[from], w);
     74             h[from] = ce;
     75         }
     76         Edge& operator [] (int pos) {
     77             return edge[pos];
     78         }
     79 }MapManager;
     80 #define m_begin(g, i) (g).h[(i)]
     81 ///map template ends
     82 
     83 int n;
     84 long long bmin, bmax;
     85 MapManager g;
     86 int* a;
     87 int moder = inf;
     88 
     89 inline void init() {
     90     readInteger(n);
     91     readInteger(bmin);
     92     readInteger(bmax);
     93     a = new int[(const int)(n + 1)];
     94     for(int i = 1; i <= n; i++) {
     95         readInteger(a[i]);
     96         if(a[i] == 0) {
     97             i--, n--;
     98             continue;
     99         }
    100         smin(moder, a[i]);
    101     }
    102 }
    103 
    104 boolean *visited;
    105 long long* dis;
    106 queue<int> que;
    107 inline void spfa(int s) {
    108     visited = new boolean[(const int)(moder)];
    109     dis = new long long[(const int)(moder)];
    110     memset(visited, false, sizeof(boolean) * (moder));
    111     memset(dis, 0x7f, sizeof(long long) * (moder));
    112     dis[s] = 0;
    113     que.push(s);
    114     while(!que.empty()) {
    115         int e = que.front();
    116         que.pop();
    117         visited[e] = false;
    118         for(int i = m_begin(g, e); i != 0; i = g[i].next) {
    119             int &eu = g[i].end;
    120             if(dis[e] + g[i].w < dis[eu]) {
    121                 dis[eu] = dis[e] + g[i].w;
    122                 if(!visited[eu]) {
    123                     que.push(eu);
    124                     visited[eu] = true;
    125                 }
    126             }
    127         }
    128     }
    129 }
    130 
    131 inline long long calc(long long x) {
    132     long long ret = 0;
    133     for(int i = 0; i < moder; i++) {
    134         if(dis[i] <= x)
    135             ret += (x - dis[i]) / (long long)moder + 1;
    136     }
    137     return ret;
    138 }
    139 
    140 inline void solve() {
    141     g = MapManager(moder, moder * n * 2);
    142     for(int i = 0; i < moder; i++) {
    143         for(int j = 1; j <= n; j++) {
    144             if(a[j] == moder) continue;
    145             g.addEdge(i, (i + a[j]) % moder, a[j]);
    146         }
    147     }
    148     spfa(0);
    149     long long res = calc(bmax) - calc(bmin - 1);
    150     printf(AUTO, res);
    151 }
    152 
    153 int main() {
    154     init();
    155     solve();
    156     return 0;
    157 }
  • 相关阅读:
    TCP报文
    TCP概述
    UDP
    传输层概述
    端口地址转换 PAT
    网络地址转换NAT原理介绍
    js的时间处理函数
    正则表达式相关笔记
    微信小程序实现图片拖拽
    在React中使用less
  • 原文地址:https://www.cnblogs.com/yyf0309/p/6613455.html
Copyright © 2020-2023  润新知