码迷,mamicode.com
首页 > 其他好文 > 详细

[国家集训队]墨墨的等式

时间:2018-10-28 11:15:32      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:max   script   size   return   lse   amp   string   sam   als   

Description

墨墨突然对等式很感兴趣,他正在研究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。

题解

可以用完全背包做

复杂度\(O(nm)\)

显然过不了

但是我们发现\(Vmax\)很小

所以可以用类似于同余的思想来做

可以找一个权值最小的点v

如果tot可以被凑出来,那么\(tot+k*v(k∈Z)\)都可以被凑出来

这样问题就可以变成了最短路了

这样我们就可以建图了

以权值为点

对于每一个点,都枚举点\(0 ~ v-1\),然后由\(v_i\)\((v_i + a[i])\)连一条权值为\(a[i]\)的边

然后直接跑最短路求出能凑出\(0 ~ v-1\)的最小值就可以暴力算了

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define LL long long
const int N = 15 ;
const int M = 500005 ;
using namespace std ;

int val[N] , upp ;
int hea[M] , num , n ;
LL Bmax , Bmin , dis[M] ;
bool vis[M] ;
struct Node { int id ; LL dis ; };
struct E {
    int Nxt , to , dis ;
} edge[M << 3] ;
priority_queue < Node > q ;
inline bool operator < (Node a , Node b) {  return a.dis > b.dis ; }
inline void add_edge(int from , int to , int dis) {
    edge[++num].Nxt = hea[from] ;
    edge[num].to = to ;
    edge[num].dis = dis ;
    hea[from] = num ;
}
inline void Dijkstra() {
    memset(vis , false , sizeof(vis)) ;
    memset(dis , 63 , sizeof(dis)) ;
    dis[0] = 0LL ; q.push((Node){ 0 , 0 }) ;
    while(!q.empty()) {
        int u = q.top().id ; q.pop() ;
        if(vis[u]) continue ; vis[u] = true ;
        for(int i = hea[u] ; i ; i = edge[i].Nxt) {
            int v = edge[i].to ;
            if(dis[v] > dis[u] + edge[i].dis) {
                dis[v] = dis[u] + edge[i].dis ;
                if(vis[v]) continue ;
                q.push((Node) { v , dis[v] }) ;
            }
        }
    }
}
inline LL Solve(LL x) {
    LL Ans = 0 ;
    for(int i = 0 ; i < upp ; i ++)
        if(dis[i] <= x)
            Ans += (x - dis[i]) / upp + 1 ;
    return Ans ;
}
int main() {
    cin >> n >> Bmin >> Bmax ;
    for(int i = 1 ; i <= n ; i ++) {
        cin >> val[i] ;
        if(!val[i]) -- n , -- i ; 
    }
    sort(val + 1 , val + n + 1) ;
    upp = val[1] ;
    for(int i = 0 ; i < upp ; i ++)
        for(int j = 1 , x ; j <= n ; j ++) {
            x = (i + val[j]) % upp ;
            add_edge(i , x , val[j]) ;
        }
    Dijkstra() ;
    cout << Solve(Bmax) - Solve(Bmin - 1) << endl ;
    return 0 ;
}

[国家集训队]墨墨的等式

标签:max   script   size   return   lse   amp   string   sam   als   

原文地址:https://www.cnblogs.com/beretty/p/9864532.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!