您的位置:首页 > 其它

bzoj 2118 墨墨的等式 dijkstra

2017-07-08 23:48 323 查看
题目链接点这里

唔,先说点关于题目的但是对于此题没用的东西。。

如果gcd(a,b)=1,那n*a+m*b所不能组成的最大的数是a*b-a-b,,所以如果这题范围是几百的话,那a*b才几十万,完全可以完全背包做,,,,恩,,这个和这题没毛线关系

我们在这12个数任选一个数假设a,,假设我们已经求出膜a等于x的最小的B(记做a*k+x)(a-1>=x>=0),那B集合中的每一个数都可以由某一个余数x,与其对应最小的a*k+x加上多少个B表示。。这个应该很好算了。

那怎么算出这a个余的最小a*k+x那。。。我们可以将每个余x看成一个点,,加上某个数后就变成新的余y,,x就向y连一条相应权值的边,,,,,,,,,就好了

update:看到一个加强版题目,下面有叉姐的解答:https://post.icpc-camp.org/d/674-poi-x-sums/9

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<"x"<<endl;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<LL,int> PII;
const double eps=1e-6;
const int MX=5e5+5;
const int P=23333333;
int n;
LL bmin,bmax;
int w[22];
LL d[MX];
void dijkstra(int s)
{
priority_queue<PII,vector<PII>,greater<PII> >Q;
mem(d,0x3f);
d[s]=0;
Q.push(PII(0,s));
while(!Q.empty())
{
int u=Q.top().second;
LL dis=Q.top().first;
Q.pop();
if(dis>d[u])continue;
for(int i=2; i<=n; i++)
{
int v=(u+w[i])%w[1];
if(d[v]<=dis+w[i])continue;
d[v]=dis+w[i];
Q.push(PII(d[v],v));
}
}
}
int main()
{
FIN;
while(cin>>n>>bmin>>bmax)
{
bmin--;
for(int i=1; i<=n; i++)scanf("%d",&w[i]);
sort(w+1,w+1+n);
dijkstra(0);
LL ansa=0,ansb=0;
for(int i=0; i<w[1]; i++)
{
if(d[i]<=bmin)
{
ansa=ansa+(bmin-d[i])/w[1]+1;
}
if(d[i]<=bmax)
{
ansb=ansb+(bmax-d[i])/w[1]+1;
}
}
cout<<ansb-ansa<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: