注意到状态 \(k^m \le 10^5\) 很少,考虑最短路,每个点 \(\frac{m(m-1)}{2} \le 10\) 条单向边,预处理出所有状态。
复杂度:\(O(10^6 \log 10^6 + k)\)
:::info[Code]
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,k;
struct node{int a[5];node(){memset(a,0,sizeof(a));}int get(){int res=0;for(int i=0;i<m;i++)res=res*10+a[i];return res;}void print(){for(int i=0;i<m;i++)cout<<a[i]<<' ';cout<<'\n';return;}bool operator <(const node& p)const{return 1;}
}s;
priority_queue<pair<int,node> > q;
int dis[N],vis[N];
int a[N],c[N];
node change(int x){int i=m-1;node res;while(x){res.a[i]=x%10;x/=10;i--;}return res;
}
node nxt(node x,int l,int r){for(int i=l;i<=r;i++)x.a[i]=(x.a[i]+a[i])%k;return x;
}
signed main(){freopen("in.in","r",stdin);freopen("out.out","w",stdout);cin>>n>>m>>k;for(int i=0;i<m;i++)cin>>a[i],a[i]=k-a[i];for(int i=0;i<m;i++)cin>>c[i];int x;cin>>x;s=change(x);memset(dis,0x3f,sizeof(dis));int inf=dis[0];dis[s.get()]=0;q.push(make_pair(0,s));while(!q.empty()){node u=q.top().second;q.pop();if(vis[u.get()]) continue;vis[u.get()]=1;for(int l=0;l<m;l++)for(int r=l;r<m;r++){node v=nxt(u,l,r);int w=c[l]+c[r];if(!vis[v.get()]&&dis[v.get()]>dis[u.get()]+w){dis[v.get()]=dis[u.get()]+w;q.push(make_pair(-dis[v.get()],v));}}}while(n--){cin>>x;if(dis[x]==inf) cout<<-1<<'\n';else cout<<dis[x]<<'\n';}return 0;
}
:::
