墨墨的等式

Source and Judge

bzoj2118

Analysis

请先思考后再展开

其实就是求能凑出多少个区间内的数
如果对于某个对a1的余数b最小凑出的是k,则统计k+xa1在区间内的答案即可
注意到a都很小,求k的话相当于在a1个点的图上跑最短路(直接dp应该也行)
时间复杂度 $O(nalog)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//Zory-2019
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<map>
#include<set>
#include<queue>
#include<deque>
#include<stack>
#include<bitset>
#include<vector>
#include<algorithm>
#include<iostream>
#include<deque>
using namespace std;
namespace mine
{
typedef long long ll;
const int INF=0x3f3f3f3f;
#define pr pair<ll,int>
#define FR first
#define SE second
#define MP make_pair
const int MAX_N=5e5+10;
int hou[MAX_N];ll dis[MAX_N];
struct Edge{int y,c,g;}e[MAX_N*20];
int ln=0;void ins(int x,int y,int c){e[++ln]=(Edge){y,c,hou[x]};hou[x]=ln;}
priority_queue< pr,vector<pr>,greater<pr> > q;
void dij()
{
memset(dis,63,sizeof dis);
q.push(MP(0,0));dis[0]=0;
while(q.size())
{
pr now=q.top();q.pop();int x=now.SE;
if(now.FR!=dis[x]) continue;
for(int k=hou[x];k>0;k=e[k].g)
{
int y=e[k].y;
if(dis[y]>dis[x]+e[k].c)
{
dis[y]=dis[x]+e[k].c;
q.push(MP(dis[y],y));
}
}
}
}
int a[20];
void main()
{
int n;ll l,r;scanf("%d%lld%lld",&n,&l,&r);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(int i=0;i<a[1];i++) for(int j=2;j<=n;j++) ins(i,(i+a[j])%a[1],a[j]);
dij();
ll ans=0;
for(int b=0;b<a[1];b++)
{
ll mi=dis[b];if(mi>r) continue;
if(mi<l) mi+=(ll)a[1]*(int)ceil(double(l-mi)/a[1]);
ans+=(r-mi)/a[1]+1;
}
printf("%lld",ans);
}
};
int main()
{
srand(time(0));
mine::main();
}

本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
本文地址:http://zory.ink/posts/cf0b.html
转载请注明出处,谢谢!