NC25351. Center Street
描述
在哈乐冰的中央大街上有N个仓买, 我们可以将其抽象为一条线段上有N个顶点,仓买在线段上是均匀分布的,也就是说1号仓买在顶点1这个位置,2号仓买在顶点2这个位置...N号仓买在N这个位置。刚开始这些仓买之间是互相不通的,为了交流,工程师们建了一些路,但是由于资金有限,并不能在两两之间建一条路,他们只能有选择的建一些路。如果两个仓买A,B满足A是B的倍数,则A,B之间可以通一条路,当然这些路是双向的,A可以到B,B可以到A
例如N=8的时候:
仓买1向所有其他仓买通一条路。
2号仓买向4,6,8号仓买通路。
3号仓买仅和6号仓买通路。
4号仓买仅和8号仓买通路。
众所周知,建路需要花费很大一笔钱,所以资本家们需要过路的人需要收取一定费用,如果仓买A,B之间通路,则过路费为元。
现在小M站在1号仓买上,他想得知他分别到达1,2,3...N号仓买的最小花费。虽然他可以直接从1号仓买到达其他仓买,但是可以通过中转的方式让花费更少。你能帮帮他吗?
输入描述
输入一个整数,表示共有N个仓买。
输出描述
一行,输出N个整数,以空格隔开,分别代表从1号仓买到其他仓买的最小花费。
示例1
输入:
8
输出:
0 1 4 5 16 13 36 21
说明:
1号到1号仓买自身,不需花费,为0
1号到2号仓买,直接到达,花费
1号到3号仓买,直接到达,花费
1号到4号仓买,直接到达花费9。但是可以先到达2,再通过2到4的路到达,花费为
1号到5号仓买,直接到达,花费16
1号到6号仓买,1->3->6,花费13
1号到7号仓买,1->7,花费36
1号到8号仓买,通过1->2->4->8,花费为21
C++14(g++5.4) 解法, 执行用时: 188ms, 内存消耗: 9928K, 提交时间: 2019-04-27 08:52:39
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll dp[500005]; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) dp[i]=1e18; dp[1]=0; for(int i=1;i<=n;i++) for(int j=2*i;j<=n;j+=i) dp[j]=min(dp[j],dp[i]+1ll*(j-i)*(j-i)); for(int i=1;i<=n;i++) printf("%lld ",dp[i]); }
C++11(clang++ 3.9) 解法, 执行用时: 70ms, 内存消耗: 10084K, 提交时间: 2019-04-25 21:27:31
#include<bits/stdc++.h> #define ll long long using namespace std; ll dp[500005]; int main(){ int n; dp[1]=0; cin>>n; for(int i=2;i<=n;i++) dp[i]=1e18; for(int i=1;i<=n;i++) for(int j=i+i;j<=n;j+=i){ dp[j]=min(dp[j],dp[i]+1LL*(j-i)*(j-i)); } for(int i=1;i<=n;i++) cout<<dp[i]<<" "; return 0; }