2118: 墨墨的等式

来源:互联网 发布:快乐园丁软件 编辑:程序博客网 时间:2024/04/30 05:31

题目链接

n[L,R]

题解:先用前缀和转化一下问题,变成求[0,X]内能凑出的数

如果物品数量可以为负,求个gcd就可以了

现在物品数字非负
mn=min(a[i]),xx+mn

mndis[i]x mod mn = ix
a[i]d[u]d[u]d[(u+a[i]) mod  mn]a[i]
这样就可以用最短路做了

mn取最小的a[i]是为了让点数最少,mn取大一些对正确性没有影响

详细版

我的收获:模型强啊,跪啊

#include <cstdio>  #include <cstring>  #include <cstdlib>  #include <cmath>  #include <iostream>  #include <algorithm>  #include <queue>  using namespace std;  #define M 500010   #define INF 1e60#define pii pair<long long,int>  int n,m,mn,t,head[M],a[20];  long long L,R,dis[M];   bool vis[M];struct edge{int to,val,nex;}e[M*20];priority_queue<pii,vector<pii>,greater<pii> > q;  void add(int u,int v,int z){e[t]=(edge){v,z,head[u]};head[u]=t++;} void dijkstra(){      memset(vis,0,sizeof(vis));      for(int i=0;i<mn;i++) dis[i]=INF;      dis[0]=0;q.push(make_pair(0,0));      while(!q.empty())    {          int u=q.top().second;q.pop();          if(vis[u]) continue;vis[u]=1;          for(int i=head[u];i!=-1;i=e[i].nex){            int v=e[i].to;            if(dis[v]>dis[u]+e[i].val) dis[v]=dis[u]+e[i].val,q.push(make_pair(dis[v],v));          }    }}  long long cal(long long x){    long long ans=0;    for(int i=0;i<mn;i++)         if(dis[i]<=x) ans+=(x-dis[i])/mn+1;//计算有多少个k满足k*mn+i<=x,因为k>=0,所以还要加1    return ans;}void work(){    dijkstra();    cout<<cal(R)-cal(L-1)<<endl;}void init(){    t=0;memset(head,-1,sizeof(head));    cin>>n>>L>>R;mn=INF;    for(int i=1;i<=n;i++) scanf("%d",&a[i]),mn=min(mn,a[i]);    for(int i=0;i<mn;i++)          for(int j=1;j<=n;j++)              if(a[j]%mn!=0) add(i,(i+a[j])%mn,a[j]);}int main()  {      init();    work();    return 0;  }  

“`

原创粉丝点击