• 2612. [Poi2003]Sums 题解(同余最短路)


    题目链接

    题目思路

    又学了一个神奇的东西叫做同余最短路

    给出若干个数,每个数有无限个,问用这些数能组成(加起来)多少个不同的数

    差不多是这个意思

    讲解链接

    对于这个题目来说

    设d[i]表示能拼出的x中满足x%a[0]=i的最小的x,其中d[0]=0。

    若d[x%a[0]]<=x,则一定可以拼出x,否则一定不可以。

    建出带权有向图,点的标号从0到a[0]-1,i号点向(i+a[j])%a[0]号点连边,边权为a[j]。

    参考链接

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    #define fi first
    #define se second
    #define debug printf("aaaaaaaaaaa\n");
    const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7,mul=233;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const double eps=1e-7;
    int n,k;
    int a[maxn];
    int head[maxn],cnt;
    int dis[maxn];
    struct edge{
        int to,next,w;
    }e[maxn];
    void add(int u,int v,int w){
        e[++cnt]={v,head[u],w};
        head[u]=cnt;
    }
    void dij(int x){
    	priority_queue<pii,vector<pii>,greater<pii> > que;
    	memset(dis,0x3f,sizeof(dis));
    	dis[x]=0;
    	que.push({0,x});
    	while(!que.empty()){
    		int len=que.top().first;
    		int pos=que.top().second;
    		que.pop();
    		if(len!=dis[pos]) continue;
            for(int i=1;i<=n;i++){
                if(dis[(pos+a[i])%a[1]]>dis[pos]+a[i]){
                    dis[(pos+a[i])%a[1]]=dis[pos]+a[i];
                    que.push({dis[(pos+a[i])%a[1]],(pos+a[i])%a[1]});
                }
            }
    
    	}
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        dij(0);
        scanf("%d",&k);
        for(int i=1,x;i<=k;i++){
            scanf("%d",&x);
            printf(dis[x%a[1]]<=x?"TAK\n":"NIE\n");
        }
        return 0;
    }
    
    
  • 相关阅读:
    kill eclipse
    C语言之表达式运算整体提升
    查找函数对比:findall,search,match
    Linux backtrace()
    git本地协同
    git 撤销push到服务器的代码
    gtest
    C陷阱篇之enum默认长度
    程序员中文开发者手册
    C语言错题分析
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/15548425.html
Copyright © 2020-2023  润新知