bzoj 2118

2118: 墨墨的等式

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 2390  Solved: 937
[Submit][Status][Discuss]

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。

此题用最短路来解决背包问题,这类问题有以下特征:

物品数量无穷

物品体积不大

目标体积较大

这类问题通过转化为模域的存在性来求解。

不多说,附代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "cstdlib"
#include "queue"
#include "cctype"
#include "algorithm"
using namespace std;
const int maxn = 500005;

int n ,num[25] ,que[maxn+5] ,head ,minn ,tail;
long long from ,to ,dis[maxn];
bool vis[maxn];
void read(int &x)
{
	x = 0;
	char c = getchar();
	while(!isdigit(c))
		c = getchar();
	while(isdigit(c))
	{
		x = (x<<3) + (x<<1) + c - ‘0‘;
		c = getchar();
	}
	return ;
}

long long qry(long long x)
{
	long long t = 0;
	for(int i=0; i<minn; i++)
		if(dis[i] <= x)
			t+=(x-dis[i])/minn+1;
	return t;
}

int main()
{
	read(n);
	scanf("%lld%lld" ,&from ,&to);
	minn = 1e6;
	for(int i = 1; i <=n; i++)
	{
		read(num[i]);
		if(!num[i])
		{
			i--;
			n--;
			continue;
		}
		minn = min(minn ,num[i]);
	}
	for(int i=1; i<minn; i++) dis[i] = to+1;
	que[++head] = 0;
	vis[0] = 1;
	while(tail != head)
	{
		tail =tail%maxn+1;
		int t = que[tail];
		vis[t] = 0;
		for(int i=1; i<=n; i++)
		{
			int y = (num[i]+t)%minn;
			if(dis[t]+num[i] < dis[y])
			{
				dis[y] = dis[t]+num[i];
				if(!vis[y])
				{
					head = head%maxn+1;
					que[head] = y;
					vis[y] = 1;
				}
			}
		}
	}
	long long ans = qry(to) - qry(from-1);
	printf("%lld\n" ,ans);
	return 0;
}

  

时间: 2024-08-29 14:47:54

bzoj 2118的相关文章

【BZOJ 2118】 2118: 墨墨的等式 (最短路)

2118: 墨墨的等式 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+-+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数列的长度.B的下界.B的上界.输入的第二行包含N个整数,即数列{an}的值. Output 输出一个整数,表示有多少b可以使等式存在非负整数解. Sample Input 2 5 1

BZOJ 2118: 墨墨的等式

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1656  Solved: 650[Submit][Status][Discuss] Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数

(最短路) bzoj 2118

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 479  Solved: 183[Submit][Status][Discuss] Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数列

数论+spfa算法 bzoj 2118 墨墨的等式

2118: 墨墨的等式 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1283  Solved: 496 Description 墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N.{an}.以及B的取值范围,求出有多少B可以使等式存在非负整数解. Input 输入的第一行包含3个正整数,分别表示N.BMin.BMax分别表示数列的长度.B的下界.B的上界.输入的第二行包含N个

BZOJ 2118 墨墨的等式(最短路)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2118 [题目大意] 求a1x1+a2y2+…+anxn=B在B的取值范围,有多少B可以使等式存在非负整数解. [题解] 同余最短路,不等式解集计数即可. [代码] #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int N=500010; n

BZOJ 2118 Dijkstra

思路: 经典题 不解释 找到最小的数mn 所有都是在mod mn的意义下 搞得 i->(i+a[i])%mn  边权为a[i] //By SiriusRen #include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=500000*13,inf=0x3f3

BZOJ 2118 墨墨的等式(最短路)

很开拓眼界的题.. 题意:给出一个n元一次方程形如a1*x1+a2*x2...+an*xn=B,求满足解集为非负整数的B值在[L,R]范围内的种数.(n<=12,ai<=5e5,L<=R<=1e12) 如果要求解集可以为负数,那么根据扩展欧几里得即可快速得到答案. 现在的问题更像一个多重背包,但是L和R太大. 首先可以把答案差分,变成求[0,R]和[0,L-1]. 我们可以这样来考虑,如果我们找到B的一个任意解m,那么m+x1,m+2*x1,,,m+k*x1..这些显然也是解. 而

BZOJ 2118 墨墨的等式 堆优化Dijkstra

题目大意:给定n个物品,每个物品有一个非负价值,问[L,R]区间内有多少价值可以被凑出来 好题!!! 如果物品数量可以为负,显然求个gcd就行了 现在物品数量必须非负 任选一个ai>0,如果一个价值k?ai+x(0≤x<ai,k≥0)可以被凑出来,那么显然(k+1)?ai+x,(k+2)?ai+x,...都可以被凑出来 显然如果我们对于每个x都找到最小的k满足k?ai+x可以被凑出来,这个问题就解决了 那么怎么求呢?最短路,使用堆优化Dijkstra即可 时间复杂度O(n?ai?log2ai)

【BZOJ】2118 墨墨的等式

[解析]最短路 [Overview]给定n个物品,每个物品有一个非负价值,问[L,R]区间内有多少价值可以被凑出来. [Analysis] 这道题很多神犇的题解都写得模模糊糊的,貌似看了好久才弄懂,下面是原创啊. 生成函数?TLE. 对于区间[l,r]的答案,可以通过差分转化为 1到r的答案数 - 1到(l-1)的答案数. 注意这道题是求有多少个值能被凑出来,而不是有多少种方法,只要判断一个值行不行就可以了. 选取一个数x=p[rand()%n+1],假设可以凑出值a满足 a mod x=b,0