这个题目是给出几个递推式,根据题目的递推式先计算出Z数组。然后根据Z数组得出一个N个点的完全图的所有边的权值信息,然后求出从0号结点到其它点的最短路径Di,然后找到所有Di%M最小的值。
这个题好像没什么需要注意,按照公式一步步计算,然后用堆优化的迪杰斯特拉算法(大白书上有)计算最短路即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
const int N = 1000000;
LL x[N], y[N], z[N], c[1000][1000];
int n, m, ans;
void init(){
for(int i=2; i<n*n; i++){
x[i] = (12345 + x[i-1] * 23456 + x[i-2] * 34567 + x[i-1] * x[i-2] * 45678) % 5837501;
y[i] = (56789 + y[i-1] * 67890 + y[i-2] * 78901 + y[i-1] * y[i-2] * 89012) % 9860381;
}
}
void make_map(){
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
c[i][j] = i==j? 0 : z[i*n+j];
}
}
}
struct Node{
int id;
LL d;
Node(){}
Node(int id, LL d):id(id),d(d){}
bool operator < (const Node& tmp)const{
return d>tmp.d;
}
};
bool done[1000];
int dij(){
int ans = m;
memset(done,0,sizeof(done));
priority_queue<Node> Q;
done[0] = 1;
for(int i=1; i<n; i++) Q.push(Node(i, c[0][i]));
while(!Q.empty()){
Node p=Q.top(); Q.pop();
if(done[p.id]) continue;
done[p.id] = 1;
int tmp = p.d%m;
ans = min(ans, tmp);
for(int i=0; i<n; i++){
if(!done[i]){
Q.push(Node(i, p.d+c[p.id][i]));
}
}
}
return ans;
}
int main(){
while(~scanf("%d %d %I64d %I64d %I64d %I64d", &n, &m, x, x+1, y, y+1)){
init();
for(int i=0; i<n*n; i++){
z[i] = (x[i] * 90123 + y[i]) % 8475871 + 1;
}
make_map();
printf("%d\n", dij());
}
return 0;
}