• bzoj2118(加法原理)(墨墨的等式)


    题目大意:给定n个物品,每个物品有一个非负价值,问[L,R]区间内有多少价值可以被凑出来。

    题意网上一大片,具体求解过程是利用了加法原理,将各个模数拥有的个数之和相加。

    就是说随机取一个数a[k],那么就是对于每个模数,通过转移的方式求出到达每个模数的最短路,将每个模数

    0-(a[k]-1)之间的数连每个对应的a[j] (%a[k])意义下,花费为路的长度,这样就好了,最后前缀和相减求答案。

     1 #include<cmath>
     2 #include<queue>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<cstring>
     6 #include<iostream>
     7 #include<algorithm>
     8 using namespace std;
     9 
    10 typedef long long ll;
    11 typedef pair<ll,int>fzy;
    12 const ll INF=1e16+7;
    13 
    14 
    15 int n;
    16 int a[17];
    17 int cnt,head[500007],next[5000007],rea[5000007],val[5000007];
    18 ll ans=0,l,r,dis[500007];
    19 bool boo[500007];
    20 
    21 struct cmp
    22 {
    23     bool operator()(fzy x,fzy y)
    24     {
    25         return x.first>y.first;
    26     }     
    27 };
    28 priority_queue<fzy,vector<fzy>,cmp>q;
    29 
    30 void add(int u,int v,int fee)
    31 {
    32     cnt++;
    33     next[cnt]=head[u];
    34     head[u]=cnt;
    35     rea[cnt]=v;
    36     val[cnt]=fee;
    37 }
    38 void Dijkstra()
    39 {
    40     for (int i=0;i<a[1];i++)
    41         dis[i]=INF,boo[i]=0;
    42     dis[0]=0;
    43     q.push(make_pair(0,0));
    44     while (!q.empty())
    45     {
    46         fzy now=q.top();
    47         q.pop();
    48         int u=now.second;
    49         if (boo[u]) continue;boo[u]=1;
    50         for (int i=head[u];i!=-1;i=next[i])
    51         {
    52             int v=rea[i],fee=val[i];
    53             if (dis[v]>dis[u]+fee)
    54             {
    55                 dis[v]=dis[u]+fee;
    56                 q.push(make_pair(dis[v],v));
    57             }
    58         }
    59     }    
    60 }
    61 int main()
    62 {
    63     memset(head,-1,sizeof(head));
    64     scanf("%d%lld%lld",&n,&l,&r);
    65     for (int i=1;i<=n;i++)
    66         scanf("%d",&a[i]);
    67     sort(a+1,a+n+1);
    68     for (int i=0;i<a[1];i++)
    69         for (int j=2;j<=n;j++)
    70             add(i,(a[j]+i)%a[1],a[j]);
    71     Dijkstra();
    72     for (int i=0;i<a[1];i++)
    73     if (dis[i]<=r)
    74     {
    75         ll x=max((ll)0,(l-dis[i])/a[1]),y=(ll)(r-dis[i])/a[1];
    76         if (x*a[1]+dis[i]<l) x++;
    77         if (y*a[1]+dis[i]>r) y--;
    78         ans+=y-x+1;    
    79     }
    80     printf("%lld
    ",ans);
    81 }
  • 相关阅读:
    smokeping一键安装脚本
    IIS与Apache禁止IP地址直接访问网站
    linux 常用命令
    ELK安装
    MySQL5.7安装
    Centos7 动态创建文件系统
    python学习第十六天 内置函数2,匿名函数
    python学习第十五天 内置函数1
    python学习第十四天 生成器函数进阶 生成器表达式 各种推导式
    python学习第十三天 迭代器 生成器
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7429635.html
Copyright © 2020-2023  润新知