[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 */