# Codeforces Round #677 (Div. 3)

## A. Boring Apartments

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
int sum, a[100005];
int main(){
for (int i = 1; i <= 9;i++){
for (int j = 1; j <= 4;j++){
sum += j;
int temp = i;
for (int k = 1; k < j;k++){
temp = temp * 10 + i;
}
a[temp] = sum;
}
}
int n;
cin >> n;
while(n--){
int x;
cin >> x;
cout << a[x] << endl;
}
return 0;
}


## B. Yet Another Bookshelf

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
int t, n;
int main(){
cin>>t;
while(t--){
cin>>n;
int x,flag=0,cnt=0,cnt0=0;
for (int i = 0; i < n;i++){
cin >> x;
if(x==1&&flag==0){
flag = 1;
}
else if(flag==1&&x==0){
cnt++;
cnt0++;
}
else if(x==1&&flag==1){
cnt0 = 0;
}
}
cout << cnt - cnt0 << endl;
}
return 0;
}


## C. Dominant Piranha

#include<bits/stdc++.h>

using namespace std;

const int N = 3e5 + 5;
int t, n, maxn, anss,x,a[N],flag=0;
int main(){
cin>>t;
while(t--){
cin >> n;
maxn = -1;
for (int i = 1; i <= n;i++){
cin >> a[i];
maxn = max(maxn, a[i]);
}
anss = -1;
for (int i = 1; i <= n;i++){
if(i==1){
if(a[i]==maxn&&a[i+1]!=a[i]){
anss = i;
break;
}
}
else if(i==n){
if(a[i]==maxn&&a[i-1]!=a[i]){
anss = i;
break;
}
}
else{
if(a[i]==maxn&&(a[i-1]!=a[i]||a[i+1]!=a[i])){
anss = i;
break;
}
}
}
cout << anss << endl;
}
return 0;
}


## D. Districts Connection

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
int t, n,other,a[5005];
vector<int> anss[2];
int main(){
cin>>t;
while(t--){
cin >> n;
other = 0;
anss[0].clear();
anss[1].clear();
for (int i = 1; i <= n;i++){
cin >> a[i];
if(a[i]!=a[1]){
anss[0].push_back(i);
other = i;
}
}
if(other==0){
cout << "NO" << endl;
}
else{
cout << "YES" << endl;
for (int i = 2; i <= n;i++){
if(a[i]==a[1]){
anss[1].push_back(i);
}
}
for (int i = 0; i < anss[0].size();i++){
cout << 1 << ‘ ‘ << anss[0][i] << endl;
}
for (int i = 0;i<anss[1].size();i++){
cout << other << ‘ ‘ << anss[1][i] << endl;
}
}
}
return 0;
}


## E. Two Round Dances

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
long long anss=1,n;
int main(){
cin>>n;
for (int i = (n / 2) + 1; i <= n; i++){
anss *= i;
}
for (int i = 1; i <= (n / 2);i++){
anss /= i;
}
for (int i = (n / 2) - 1; i >= 1;i--){
anss *= i;
}
for (int i = (n / 2) - 1; i >= 1;i--){
anss *= i;
}
cout << anss / 2 << endl;
return 0;
}


## F. Zero Remainder Sum

$$dp[x][y][cnt][rem]$$代表当前位置为$$(x,y)$$ 已经选取了$$cnt$$个元素且余数是$$rem$$

$$dp[1][1][0][0]=0$$代表最初的位置
$$dp[nx][ny][cnt][rem] = max(dp[nx][ny][cnt][rem],dp[x][y][cnt][rem])$$ 表示不取当前元素
$$dp[nx][ny][cnt + 1][(rem+a_{ij})\%k] = max(dp[nx][ny][cnt+1][(rem+a_{ij})\%k],dp[x][y][cnt][rem] + a_{ij})$$ 表示取当前元素

#include<bits/stdc++.h>

using namespace std;

const int N = 70 + 5;
int a[N][N], dp[N][N][N][N], n, m, k;
int main(){
cin >> n >> m >> k;
for (int i = 1; i <= n;i++){
for (int j = 1; j <= m;j++){
cin >> a[i][j];
}
}
memset(dp, -1, sizeof(dp));
dp[1][1][0][0] = 0;
for (int i = 1; i <= n;i++){
for (int j = 1; j <= m;j++){
for (int cnt = 0; cnt <= (m / 2);cnt++){
for (int rem = 0; rem < k;rem++){
if(dp[i][j][cnt][rem]==-1){
continue;
}
int ii=i, jj=j+1;
if(j==m){
jj = 1;
ii = i + 1;
}
if(ii==i){
dp[ii][jj][cnt][rem] = max(dp[ii][jj][cnt][rem], dp[i][j][cnt][rem]);
}
else{
dp[ii][jj][0][rem] = max(dp[ii][jj][0][rem], dp[i][j][cnt][rem]);
}
if((cnt+1)<=m/2){
if(ii==i){
dp[ii][jj][cnt+1][(rem+a[i][j])%k] = max(dp[ii][jj][cnt+1][(rem+a[i][j])%k], dp[i][j][cnt][rem]+a[i][j]);
}
else{
dp[ii][jj][0][(rem+a[i][j])%k] = max(dp[ii][jj][0][(rem+a[i][j])%k], dp[i][j][cnt][rem]+a[i][j]);
}
}
}
}
}
}
cout << max(0, dp[n + 1][1][0][0]) << endl;
return 0;
}


## G. Reducing Delivery Cost

#include<bits/stdc++.h>

using namespace std;

const int N = 1e3 + 5;
int n, m, k;
typedef pair<int, int> PII;
int e[2*N], ne[2*N],w[2*N], h[N], idx,dis[N][N], st[N],mp[N][N],anss=0x3f3f3f3f;
struct node
{
int a, b, c;
};

void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

// 堆优化版dijksyta
int dijkstra(int sx) {
memset(dis[sx], 0x3f, sizeof dis[sx]);  // 初始化距离为无穷
memset(st, 0, sizeof st);
priority_queue<PII, vector<PII>, greater<PII> > q;  // 定义一个按照距离从小到大排序的优先队列，第一维:距离，第二维:点
dis[sx][sx] = 0;  // 一开始源点距离为0
q.push({0, sx});  // 把源点信息放入队列
while (q.size()) {  // 每个点只出入队列一次
auto t = q.top();
q.pop();

int distance = t.first, ver = t.second;  // 最小距离和相对应的点
if (st[ver]) continue;  // 这个操作保证每个点只出入队一次，因为队列里面可能会出现{dis1[3], 3}, {dis2[3], 3}的情况，这样保证dis1[3]<dis2[3]时，3号点只进出入队一次
st[ver] = 1;  // 标记，因为dijkstra的贪心策略保证每个点只需要进出队一次

for (int i = h[ver]; ~i; i = ne[i]) {  // 遍历ver的邻接点
int j = e[i];
if (dis[sx][j] > distance + w[i]) {
dis[sx][j] = distance + w[i];
q.push({dis[sx][j], j});  // 这里不需要判断st，因为一旦更新发现更小必须放入队列
}
}
}
}

{
int u, v, w;
};

vector<pair<int, int> >q;
int main(){
cin >> n >> m >> k;
memset(h, -1, sizeof h);
//memset(mp, 0x3f, sizeof mp);  // 初始更新每个点间距离为无穷远
for (int i = 0; i < m;i++){
int x, y, z;
cin >> node.u >> node.v >> node.w;
r.push_back(node);
//mp[node.u][node.v] = min(node.w,mp[node.u][node.v]);
}
for (int i = 1; i <= n;i++){
dijkstra(i);
}
for (int i = 0; i < k; i++)
{
int sx, tx;
cin >> sx >> tx;
q.push_back({sx, tx});
}
for (int i = 0; i < r.size();i++){
int temp = 0;
for (int j = 0; j < q.size();j++){
int sx = q[j].first;
int tx = q[j].second;
temp += min(dis[sx][tx], min(dis[sx][r[i].u] + dis[r[i].v][tx], dis[sx][r[i].v] + dis[r[i].u][tx]));
}
anss = min(temp, anss);
}
cout << anss << endl;
return 0;
}


Codeforces Round #677 (Div. 3)

(0)
(0)