[BZOJ2118]墨墨的等式(数学+图论)
2017-10-24 09:44
459 查看
题目:
我是超链接题解:
题面都错了差评!Step1、
我们只需要对于每个q (0<=q < p),计算出最小的k,使k*p+q能够能够被构造出来,那么对于k’(k’>k) k’*p+q也能构造出来对于样例来说
模数可以为0 1 2
0- - - - - -3k+0
1- - - - - -3k+1
2- - - - - -3k+2
如果6可以达到的话,9也可以达到
Step2、
我们需要计算最小的k可以转化为计算dis[q]表示模数为q时能达到的最小价值Step3、
这个dis怎么求呢?好像可以转化为最短路问题?每一个q就是点,a的值就是边上的权值所以对于每个q建一个点,对于每个ai,从q向(q+ai)%p连一条长度为ai的边,跑一遍最短路,计算出dis
Step4、
ans=find(Bmax)-find(Bmin-1)利用差分求解代码:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #define LL long long using namespace std; const int N=5e5; struct hh{int id,dis;}; LL dis[N+5];int minn=N,cnt,a[20]; bool vis[N+5]; bool operator <(const hh a,const hh b){return a.dis>b.dis;} void dij() { priority_queue<hh>q; q.push((hh){0,0}); memset(dis,0x7f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[0]=0; while (!q.empty()) { hh now=q.top(); q.pop(); if (vis[now.id]) continue; vis[now.id]=1; for (int i=1;i<=cnt;i++) { int y=(now.id+a[i])%minn; if (dis[y]>dis[now.id]+a[i]) { dis[y]=dis[now.id]+a[i]; q.push((hh){y,dis[y]}); } } } } LL find(LL x) { LL ans=0; for (int i=0;i<minn;i++) if (x>=dis[i]) ans+=(x-dis[i])/minn+1; return ans; } int main() { LL L,R;int n,i; scanf("%d%lld%lld",&n,&L,&R); for (i=1;i<=n;i++) { scanf("%d",&a[++cnt]); if (!a[cnt]) cnt--; if (cnt) minn=min(minn,a[cnt]); } dij(); printf("%lld",find(R)-find(L-1)); }
相关文章推荐
- bzoj 2118 墨墨的等式 - 图论最短路建模
- [图论训练]BZOJ 2118: 墨墨的等式 【最短路】
- BZOJ 2118: 墨墨的等式
- BZOJ2118: 墨墨的等式
- BZOJ 2118 墨墨的等式
- BZOJ 2118 墨墨的等式
- BZOJ2118: 墨墨的等式 思维建图
- Bzoj2118 墨墨的等式
- bzoj2118 墨墨的等式
- 【bzoj2118】 墨墨的等式
- BZOJ2118: 墨墨的等式
- bzoj2118 墨墨的等式 最短路
- BZOJ 2118 墨墨的等式[Waiting]
- BZOJ 2118 墨墨的等式 最短路 同余类分析
- BZOJ2118 墨墨的等式
- bzoj 2118: 墨墨的等式
- 【BZOJ 2118】墨墨的等式
- BZOJ2118: 墨墨的等式
- BZOJ2118 墨墨的等式
- bzoj 2118: 墨墨的等式