zoukankan      html  css  js  c++  java
  • [国家集训队]墨墨的等式

    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*105,1≤BMin≤BMax≤1012。

    题解

    可以用完全背包做

    复杂度(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 ;
    }
    
  • 相关阅读:
    HDOJ 5414 CRB and String 模拟
    Python标准库:内置函数all(iterable)
    Can not find a java.io.InputStream with the name [downloadFile] in the invocation stack.
    关于TabLayout+ViewPager组合实现多页面滑动
    互联网产品经理应该具备的技能(需求篇)
    【Android】利用自己定义View的重绘实现拖动移动,获取组件的尺寸
    mybatis自己主动生成mapper,dao,映射文件
    Java解析注解
    如日中天的Uber到底是用什么开发语言做到的?
    [Swift]LeetCode1002. 查找常用字符 | Find Common Characters
  • 原文地址:https://www.cnblogs.com/beretty/p/9864532.html
Copyright © 2011-2022 走看看