【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<=b 假如凑出了a,一定能凑出a+x。

假如我们知道了对于每个b最小能凑出来的值a,
那么就能知道在余数b下共有(now-a)/x+1个不大于now的数可以被凑出。
且两个相同的值在mod x下一定有一样的余数,所以当b不同时,a一定也不同。
只要把所有b下的答案相加就是结果。

那么我们只要求出对于任意的b,a能取到的最小值。即:在mod x的余数分类为b中,所能凑出来的最小的价值。
这个东西用最短路就可以求出。

[Extended]如果每个物品有一个购买数量下限,怎样做?
解答:先把下限的值全部减掉,恢复到本题的询问。

[Sumup]
①静态的区间:差分的思想。
②缩小检索范围的方法:分类,分段。
③序列的计数是与最值联系在一起的,有时先需要分类才能存在最值。
④程序的强健性检查:注意最大值赋得对不对。

[Code]
/**************************************************************
    Problem: 2118
    User: y20070316
    Language: C++
    Result: Accepted
    Time:1860 ms
    Memory:8616 kb
****************************************************************/
 
#include 
#include 
#include 
using namespace std;
 
typedef long long LL;
const int N=13;
const int M=500001;
const LL MAX=10000000000000;
 
int n; LL BMin,BMax;
int p[N],vtx;
LL dis[M]; int q[M],h,t,v[M];
 
inline LL query(LL w)
{
    LL cnt=0;
    for (int i=0;ip[i]) vtx=p[i];
     
    int now,nxt;
    for (int i=1;i

你可能感兴趣的:(BZOJ)