2612. [Poi2003]Sums 題解(同餘最短路)
阿新 • • 發佈:2021-11-13
題目連結
題目思路
又學了一個神奇的東西叫做同餘最短路
給出若干個數,每個數有無限個,問用這些數能組成(加起來)多少個不同的數
差不多是這個意思
對於這個題目來說
設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; }