zoukankan      html  css  js  c++  java
  • bzoj2118

    2118: 墨墨的等式

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 2390  Solved: 937
    [Submit][Status][Discuss]

    Description

    墨墨突然对等式很感兴趣,他正在研究a1x1+a2x2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。

    Input

    输入的第一行包含3个正整数,分别表示N、BMin、BMax分别表示数列的长度、B的下界、B的上界。输入的第二行包含N个整数,即数列{an}的值。

    Output

    输出一个整数,表示有多少b可以使等式存在非负整数解。

    Sample Input

    2 5 10
    3 5

    Sample Output

    5

    HINT

    对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。

    分析

    我们发现这已经不是简单的数论题了!(我开始并没有发现)对于这种无限取的背包问题,可以转化为取mod最短路的问题。具体怎么想呢?

    首先我们将a排序(因为这道题n比较小其实可以不用但是这样更优秀)考虑对于a1,对于所有能够取到的数x,都有x+a1*k(k任意)一定会被取到。所以我们就可以把所有能够取到的数%a1,发现结果属于0~a1-1中的一个,那么我们就把每一个0~a1看做一个集合包括所有能够取到的数%a1=该值。

    那么最小路怎么解释呢?相当于每次加一个数就走了一条边,我们将所有<r的数%a1的最小值看做最短路,求完后遍历0~a1分别求r和l-1的组合的个数(前缀和)减去即可。

    这里我用dijkstra。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<ctype.h>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<queue>
     7 #include<utility>
     8 #include<vector>
     9 #include<functional>
    10 using namespace std;
    11 const int maxn=5e5+5;
    12 typedef long long ll;
    13 typedef pair<ll,int> pairr;
    14 
    15 int n,a[15];
    16 ll L, R;
    17 
    18 struct Edge{
    19     int to,nxt,dis;
    20 }e[maxn*10];
    21 
    22 int  head[maxn];int ecnt;
    23 
    24 inline void addedge(int  from,int to,int dis)
    25 {
    26     e[++ecnt]=(Edge){to,head[from],dis},head[from]=ecnt;
    27 }
    28 
    29 ll dis[maxn];
    30 bool vis[maxn];
    31 void dijkstra()
    32 {
    33     priority_queue <pairr,vector<pairr >,greater<pairr > >q;
    34     for(int i=0;i<a[1];i++)dis[i]=(ll)1e60;
    35     dis[0]=0;
    36     q.push(make_pair(0,0));
    37     while(!q.empty())
    38     {
    39         int v=q.top().second;q.pop();
    40         if(vis[v])continue;vis[v]=1;
    41         for(int i=head[v];i!=-1;i=e[i].nxt)
    42         {
    43             int u=e[i].to;
    44             ll w=(ll)e[i].dis;
    45             if(dis[u]>dis[v]+w)
    46             {
    47                 dis[u]=dis[v]+w;
    48                 q.push(make_pair(dis[u],u));
    49             }
    50         }
    51     }
    52 }
    53 
    54 inline ll getans(ll x)
    55 {
    56     ll ans=0;
    57     for(int i=0;i<a[1];i++)
    58         if(dis[i]<=R){
    59             ll zp=max(0ll,(x-dis[i])/a[1]);
    60             if(zp*a[1]+dis[i]<x)ans++;
    61             ans+=zp;
    62         }
    63     return ans;
    64 }
    65 
    66 int main()
    67 {
    68     scanf("%d%lld%lld",&n,&L,&R);
    69     memset(head,-1,sizeof(head));
    70     for(int i=1;i<=n;i++)
    71     {
    72         scanf("%d",&a[i]);
    73         if(a[i]==0)n--,i--;
    74     }
    75     sort(a+1,a+1+n);
    76     for(int i=0;i<a[1];i++)
    77         for(int j=2;j<=n;j++)
    78         addedge(i,(a[j]+i)%a[1],a[j]);
    79     dijkstra();
    80 //    printf("%lld\n",getans(R)-getans(L-1)+1);
    81     ll ans=0;
    82     for (int i=0;i<a[1];i++) if (dis[i]<=R) {
    83         ll l=max(0ll,(L-dis[i])/a[1]);
    84         if (l*a[1]+dis[i]<L) l++;
    85         ll r=(R-dis[i])/a[1];
    86         if (r*a[1]+dis[i]>R) r--;
    87         ans+=r-l+1;
    88     }
    89     printf("%lld\n",ans);
    90     return 0;
    91 }

    PS调了几天竟然是板子写错了!!!

  • 相关阅读:
    2021.9.15 单一职责原则
    2021.9.21 Hive元数据
    2021.9.22 抽象工厂方法模式(人与肤色)
    2021.9.25 Hive安装
    1021每日博客
    1027每日博客
    1018每日博客
    1028每日博客
    1026每日博客
    1025每日博客
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/12984482.html
Copyright © 2011-2022 走看看