bzoj 2118 墨墨的等式 dijkstra

題目鏈接點這裏

唔,先說點關於題目的但是對於此題沒用的東西。。

如果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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章