[BZOJ2118]墨墨的等式

[BZOJ2118]墨墨的等式

试题描述

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

输入

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

输出

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

输入示例

2 5 10
3 5

输出示例

5

数据规模及约定

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

题解

这题的思路我也不知道怎么想到的。。。

就是选一个数 a1,然后以它为基础做,显然所有能被拼凑出来的数都可以表示成这个形式:ki · a1 + i,然后对于每个 i 我们可以求出最小的 ki,那么 (ki + 1) · a1 + i,(ki + 2) · a1 + i,(ki + 3) · a1 + i,...,都是可以被表示出来的,那么对于能够凑出来的数模 a1 等于 i 的这一部分答案就可以用除法统计出来了。

那么如何算最小的 ki,这就是一个最短路,总共有 n 种转移,每种转移边权为 ai

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long

LL read() {
	LL x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

#define maxn 500010
#define oo (1ll << 60)

int n, A[15];
LL Bl, Br, K[maxn];

struct Node {
	LL val;
	Node() {}
	Node(LL _): val(_) {}
	bool operator < (const Node& t) const { return val > t.val; }
};
priority_queue <Node> Q;
bool vis[maxn];
void solve() {
	for(int i = 0; i < A[1]; i++) K[i] = oo;
	K[0] = 0; Q.push(Node(0));
	while(!Q.empty()) {
		Node u = Q.top(); Q.pop();
		if(vis[u.val%A[1]]) continue;
		vis[u.val%A[1]] = 1;
		for(int i = 1; i <= n; i++) if(K[(u.val+A[i])%A[1]] > (u.val + A[i]) / A[1]) {
			K[(u.val+A[i])%A[1]] = (u.val + A[i]) / A[1];
			if(!vis[(u.val+A[i])%A[1]]) Q.push(Node(u.val + A[i]));
		}
	}
	return ;
}

LL Div(LL a, LL b) {
	int fl = 1;
	if(a < 0) fl = -fl;
	if(b < 0) fl = -fl;
	if(fl > 0) return a / b;
	if(a % b) return a / b - 1;
	return a / b;
}

int main() {
	n = read(); Bl = read() - 1; Br = read();
	for(int i = 1; i <= n; i++) A[i] = read();
	
	solve();
	LL ans = 0;
	for(int i = 0; i < A[1]; i++) {
		LL xl = Div(Bl - i, (LL)A[1]) + 1, xr = Div(Br - i, (LL)A[1]);
		if(xr >= max(xl, K[i])) ans += xr - max(xl, K[i]) + 1;
	}
	printf("%lld\n", ans);
	
	return 0;
}
/*
in:
10 2333 666666666666
100000 2342 32768 500000 36 216 1296 7776 46656 279936
out:
333333323324
*/

 

posted @ 2017-03-31 10:08  xjr01  阅读(265)  评论(0编辑  收藏  举报