2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution
A:Exam
Solved.
温暖的签。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + ; int k;
char str1[maxn], str2[maxn]; int main()
{
while(~scanf("%d",&k))
{
scanf("%s", str1 + );
scanf("%s", str2 + );
int cnt1 = , cnt2 = ;
int len = strlen(str1 + );
for(int i = ; i <= len; ++i)
{
if(str1[i] == str2[i]) cnt1++;
else cnt2++;
}
int ans = ;
if(cnt1 >= k)
{
ans = k + cnt2;
}
else
{
ans = len - (k - cnt1);
}
printf("%d\n", ans);
}
return ;
}
B:Coprime Integers
Solved.
枚举gcd反演
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e7 + ; bool check[maxn];
int prime[maxn];
ll mu[maxn]; void Moblus()
{
memset(check, false, sizeof check);
mu[] = ;
int tot = ;
for(int i = ; i < maxn; ++i)
{
if(!check[i])
{
prime[tot++] = i;
mu[i] = -;
}
for(int j = ; j < tot; ++j)
{
if(i * prime[j] > maxn) break;
check[i * prime[j]] = true;
if(i % prime[j] == )
{
mu[i * prime[j]] = ;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
} ll sum[maxn]; ll calc(int n, int m)
{
ll ans = ;
if(n > m) swap(n, m);
for(int i = , la = ; i <= n; i = la + )
{
la = min(n / (n / i), m / (m / i));
ans += (ll)(sum[la] - sum[i - ]) * (n / i) * (m / i);
}
return ans;
} ll a, b, c, d; int main()
{
Moblus();
for(int i = ; i < maxn; ++i) sum[i] = sum[i - ] + mu[i];
while(~scanf("%lld %lld %lld %lld", &a, &b, &c, &d))
{
ll ans = calc(b, d) - calc(a - , d) - calc(b, c - ) + calc(a - , c - );
printf("%lld\n", ans);
}
return ;
}
C:Contest Setting
Solved.
题意:
有n个题目,每个题目的难度值不同,要选出k个组成一套$Contest$
要求每个题目难度不同,求方案数
思路:
$把难度值相同的题目放在一起作为一种 dp[i][j] 表示选到第i种题目,已经选了k种的方案数$
$然后做01背包即可,注意加上的值为cnt[i] 表示该种题目有多少个$
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD = ;
const int maxn = 1e3 + ; int n, k, pos;
ll cnt[maxn];
ll dp[maxn];
map<int, int>mp; int main()
{
while(~scanf("%d %d", &n, &k))
{
mp.clear();
pos = ;
memset(cnt, , sizeof cnt);
for(int i = ; i <= n; ++i)
{
int num;
scanf("%d", &num);
if(mp[num] == ) mp[num] = ++pos;
int id = mp[num];
cnt[id]++;
}
memset(dp, , sizeof dp);
dp[] = ;
for(int i = ; i <= pos; ++i)
{
for(int j = k; j >= ; --j)
{
dp[j] = (dp[j] + dp[j - ] * cnt[i] % MOD) % MOD;
}
}
printf("%lld\n", dp[k]);
}
return ;
}
D:Count The Bits
Solved.
题意:
在$[0, 2^b - 1] 中所有k的倍数以二进制形式表示有多少个1$
思路:
$dp[i][j] 表示枚举二进制位数,j 模k的余数, 表示的是前i位中模k的余数为j的数中1的个数$
$cnt[i][j] 表示当前二进制位为第i位, 模k的余数为j的数的个数$
直接转移即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD = (ll)1e9 + ;
const int maxn = 1e3 + ; int k, b;
ll cnt[maxn][maxn];
ll dp[maxn][maxn]; int main()
{
while(~scanf("%d %d", &k, &b))
{
memset(cnt, , sizeof cnt);
memset(dp, , sizeof dp);
cnt[][]++;
cnt[][ % k]++;
dp[][ % k]++;
ll tmp = ;
for(int i = ; i <= b; ++i)
{
tmp = (tmp << ) % k;
for(int j = ; j < k; ++j)
{
//
cnt[i + ][j] = (cnt[i + ][j] + cnt[i][j]) % MOD;
dp[i + ][j] = (dp[i + ][j] + dp[i][j]) % MOD;
//
ll tmp2 = (tmp + j) % k;
cnt[i + ][tmp2] = (cnt[i + ][tmp2] + cnt[i][j]) % MOD;
dp[i + ][tmp2] = ((dp[i + ][tmp2] + cnt[i][j]) % MOD + dp[i][j]) % MOD;
}
}
printf("%lld\n", dp[b][]);
}
return ;
}
#include <bits/stdc++.h>
using namespace std; #define N 1010
#define ll long long
const ll MOD = (ll)1e9 + ;
ll dp[N][N], cnt[N][N];
int n, k; int main()
{
while (scanf("%d%d", &k, &n) != EOF)
{
memset(dp, , sizeof dp);
memset(cnt, , sizeof cnt);
++dp[][ % k];
++cnt[][ % k];
++cnt[][];
ll tmp = % k;
for (int i = ; i <= n; ++i)
{
tmp = tmp * % k;
for (int j = ; j < k; ++j)
{
dp[i][j] = dp[i - ][j];
cnt[i][j] = cnt[i - ][j];
if (j - tmp >= )
{
dp[i][j] = (dp[i][j] + dp[i - ][j - tmp] + cnt[i - ][j - tmp]) % MOD;
cnt[i][j] = (cnt[i][j] + cnt[i - ][j - tmp]) % MOD;
}
else
{
dp[i][j] = (dp[i][j] + dp[i - ][k + j - tmp] + cnt[i - ][k + j - tmp]) % MOD;
cnt[i][j] = (cnt[i][j] + cnt[i - ][k + j - tmp]) % MOD;
}
}
}
printf("%lld\n", dp[n][]);
}
return ;
}
E:Cops And Robbers
Solved.
题意:
在一个$n * m 的矩阵中,有些地方可以建墙,但是不同的墙开销不同,求最小开销把劫匪围住$
思路:
拆点最小割,但是是点权,拆点即可。
#include<bits/stdc++.h> using namespace std; const int maxn = 4e3 + ;
const int INF = 0x3f3f3f3f; struct Edge{
int to, flow, nxt;
Edge(){}
Edge(int to, int nxt, int flow):to(to), nxt(nxt), flow(flow){}
}edge[maxn << ]; int head[maxn], dep[maxn];
int S,T;
int N, n, m, tot; void Init(int n)
{
N = n;
//memset(head, -1, sizeof head);
for(int i = ; i < N; ++i) head[i] = -;
tot = ;
} void addedge(int u, int v, int w, int rw = )
{
edge[tot] = Edge(v, head[u], w); head[u] = tot++;
edge[tot] = Edge(u, head[v], rw); head[v] = tot++;
} bool BFS()
{
//memset(dep, -1, sizeof dep);
for(int i = ; i < N; ++i) dep[i] = -;
queue<int>q;
q.push(S);
dep[S] = ;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = edge[i].nxt)
{
if(edge[i].flow && dep[edge[i].to] == -)
{
dep[edge[i].to] = dep[u] + ;
q.push(edge[i].to);
}
}
}
return dep[T] < ? : ;
} int DFS(int u, int f)
{
if(u == T || f == ) return f;
int w, used = ;
for(int i = head[u]; ~i; i = edge[i].nxt)
{
if(edge[i].flow && dep[edge[i].to] == dep[u] + )
{
w = DFS(edge[i].to, min(f - used, edge[i].flow));
edge[i].flow -= w;
edge[i ^ ].flow += w;
used += w;
if(used == f) return f;
}
}
if(!used) dep[u] = -;
return used;
} int Dicnic()
{
int ans = ;
while(BFS())
{
int tmp = DFS(S, INF);
if(tmp == INF) return -;
ans += tmp;
}
return ans;
} int c;
int C[maxn];
char mp[][]; int calc(int i, int j)
{
return i * + j;
} int main()
{
while(~scanf("%d %d %d", &m, &n, &c))
{
int base = n * + m + ;
int x, y;
Init();
for(int i = ; i <= n; ++i)
{
for(int j = ; j <= m; ++j)
{
scanf(" %c", &mp[i][j]);
if(mp[i][j] == 'B') { x = i, y = j; }
}
}
for(int i = ; i <= c; ++i) scanf("%d", C + i);
S = , T = calc(x, y);
for(int i = ; i <= n; ++i)
{
addedge(S, calc(i, ), INF);
addedge(S, calc(i, m), INF);
}
for(int i = ; i <= m; ++i)
{
addedge(S, calc(, i), INF);
addedge(S, calc(n, i), INF);
}
for(int i = ; i <= n; ++i)
{
for(int j = ; j <= m; ++j)
{
if(i != n)
{
addedge(calc(i, j) + base, calc(i + , j), INF);
addedge(calc(i + , j) + base, calc(i, j), INF);
}
if(j != m)
{
addedge(calc(i, j)+ base, calc(i, j + ), INF);
addedge(calc(i, j + ) + base, calc(i, j), INF);
}
}
}
for(int i = ; i <= n; ++i)
{
for(int j = ; j <= m; ++j)
{
if(mp[i][j] >= 'a' && mp[i][j] <= 'z')
{
addedge(calc(i, j), calc(i, j) + base, C[mp[i][j] - 'a' + ]);
}
else
{
addedge(calc(i, j), calc(i, j) + base, INF);
}
}
}
int ans = Dicnic();
printf("%d\n", ans);
}
return ;
}
F:Rectangles
Solved.
题意:
二维平面上有一些平行坐标轴的矩形,求有多少区间是被奇数个矩形覆盖。
思路:
扫描线,只是把区间加减换成区间01状态翻转,现场学扫描线可还行..
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 200010
#define pii pair <int, int>
int n, mx, my, bx[N], by[N];
ll res;
struct Rec
{
int x[], y[];
void scan()
{
for (int i = ; i < ; ++i) scanf("%d%d", x + i, y + i);
if (x[] > x[]) swap(x[], x[]);
if (y[] > y[]) swap(y[], y[]);
bx[++mx] = x[];
bx[++mx] = x[];
by[++my] = y[];
by[++my] = y[];
}
}rec[N];
vector <pii> v[N]; void Hash()
{
sort(bx + , bx + + mx);
sort(by + , by + + my);
mx = unique(bx + , bx + + mx) - bx - ;
my = unique(by + , by + + my) - by - ;
for (int i = ; i <= n; ++i)
{
for (int j = ; j < ; ++j)
{
rec[i].x[j] = lower_bound(bx + , bx + + mx, rec[i].x[j]) - bx;
rec[i].y[j] = lower_bound(by + , by + + my, rec[i].y[j]) - by;
}
}
} namespace SEG
{
struct node
{
ll sum, val;
int lazy;
node () {}
node (ll sum, ll val, int lazy) : sum(sum), val(val), lazy(lazy) {}
void init() { sum = val = lazy = ; }
node operator + (const node &other) const { return node(sum + other.sum, val + other.val, ); }
void Xor() { val = sum - val; lazy ^= ; }
}a[N << ];
void build(int id, int l, int r)
{
a[id] = node(, , );
if (l == r)
{
a[id].sum = by[l + ] - by[l];
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
a[id] = a[id << ] + a[id << | ];
}
void pushdown(int id)
{
if (!a[id].lazy) return;
a[id << ].Xor();
a[id << | ].Xor();
a[id].lazy = ;
}
void update(int id, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr)
{
a[id].Xor();
return;
}
int mid = (l + r) >> ;
pushdown(id);
if (ql <= mid) update(id << , l, mid, ql, qr);
if (qr > mid) update(id << | , mid + , r, ql, qr);
a[id] = a[id << ] + a[id << | ];
}
} int main()
{
while (scanf("%d", &n) != EOF)
{
mx = my = ; res = ;
for (int i = ; i <= * n; ++i) v[i].clear();
for (int i = ; i <= n; ++i) rec[i].scan(); Hash();
for (int i = ; i <= n; ++i)
{
v[rec[i].x[]].emplace_back(rec[i].y[], rec[i].y[] - );
v[rec[i].x[]].emplace_back(rec[i].y[], rec[i].y[] - );
}
n <<= ;
SEG::build(, , n);
for (int i = ; i < mx; ++i)
{
for (auto it : v[i]) SEG::update(, , n, it.first, it.second);
res += (bx[i + ] - bx[i]) * SEG::a[].val;
}
printf("%lld\n", res);
}
return ;
}
G:Goat on a Rope
Solved.
签到。
#include<bits/stdc++.h> using namespace std; double x, y;
double xa, xb, ya, yb; double calc(double xa, double ya, double xb, double yb)
{
return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
} int main()
{
while(~scanf("%lf %lf %lf %lf %lf %lf", &x, &y, &xa, &ya, &xb, &yb))
{
double ans = 1e9;
if(x >= min(xa, xb) && x <= max(xa, xb)) ans = min(ans, min(fabs(y - ya), fabs(y - yb)));
if(y >= min(ya, yb) && y <= max(ya, yb)) ans = min(ans, min(fabs(x - xa), fabs(x - xb)));
ans = min(ans, calc(x, y, xa, ya));
ans = min(ans, calc(x, y, xa, yb));
ans = min(ans, calc(x, y, xb, ya));
ans = min(ans, calc(x, y, xb, yb));
printf("%.3f\n", ans);
}
return ;
}
H:Repeating Goldbachs
Solved.
签到。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6 + ; bool isprime[maxn];
int prime[maxn]; void Init()
{
memset(isprime, true, sizeof isprime);
isprime[] = isprime[] = false;
for(int i = ; i < maxn; ++i)
{
if(isprime[i])
{
prime[++prime[]] = i;
for(int j = i * ; j < maxn; j += i)
{
isprime[j] = false;
}
}
}
} int x; int main()
{
Init();
while(~scanf("%d", &x))
{
int ans = ;
while(x >= )
{
for(int i = ; i <= prime[]; ++i)
{
int tmp = prime[i];
if(isprime[x - tmp])
{
++ans;
x = x - tmp - tmp;
break;
}
}
}
printf("%d\n", ans);
}
return ;
}
I:Inversions
Unsolved.
题意:
给出一些序列,一些位置上的数字可以在$[1, k]的范围内随便填,求如果填使得整个序列的逆序对个数最多$
J:Time Limits
Solved.
签到。
#include<bits/stdc++.h> using namespace std; int n, s; int main()
{
while(~scanf("%d %d", &n, &s))
{
int Max = -;
for(int i = ; i <= n; ++i)
{
int num;
scanf("%d", &num);
Max = max(Max, num);
}
Max *= s;
int ans = Max / ;
if(Max % ) ans++;
printf("%d\n", ans);
}
return ;
}
K:Knockout
Unsolved.
题意:
给出一个数字,然后两个骰子的点数,每次可以移掉数字当中某几位加起来的和等于两骰子点数之和
那么就可以移掉这几位,知道最后不能移位置,最后剩下的数就是分数
现在给出一中间局面,求移掉哪些,使得最后的分数期望最大以及最小
L:Liars
Solved.
签到。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3 + ; int n;
int cnt[maxn]; int main()
{
while(~scanf("%d", &n))
{
memset(cnt, , sizeof cnt);
for(int i = ; i <= n; ++i)
{
int ai, bi;
scanf("%d %d", &ai, &bi);
for(int j = ai; j <= bi; ++j)
{
cnt[j]++;
}
}
int ans = -;
for(int i = ; i <= n; ++i)
{
if(cnt[i] == i) ans = i;
}
printf("%d\n", ans);
}
return ;
}
M:Mobilization
Unsolved.
题意:
$有m种军队,每种军队有h_i 属性 和 p_i属性,以及购买一支军队需要c_i的钱,每种军队可以购买无限支$
$现在你有C个单位的钱,求如何购买军队,使得\sum h_i \cdot \sum p_i 最大$
2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution的更多相关文章
- 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution
A:Alphabet Solved. 签. #include<bits/stdc++.h> using namespace std; ]; ]; int main(){ scanf(); ...
- 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution
A - Odd Palindrome 水. #include <bits/stdc++.h> using namespace std; #define N 110 char s[N]; i ...
- 2018 ICPC Pacific Northwest Regional Contest I-Inversions 题解
题目链接: 2018 ICPC Pacific Northwest Regional Contest - I-Inversions 题意 给出一个长度为\(n\)的序列,其中的数字介于0-k之间,为0 ...
- 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)
2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 思路: A Exam 思路:水题 代码: #include<bits ...
- Contest Setting 2018 ICPC Pacific Northwest Regional Contest dp
题目:https://vj.69fa.cn/12703be72f729288b4cced17e2501850?v=1552995458 dp这个题目网上说是dp+离散化这个题目要对这些数字先处理然后进 ...
- 2015-2016 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) S Surf
SurfNow that you've come to Florida and taken up surng, you love it! Of course, you've realized that ...
- 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) 题解
[题目链接] A - Alphabet 最长公共子序列.保留最长公共子序列,剩余的删除或者补足即可. #include <bits/stdc++.h> using namespace st ...
- 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) K Tournament Wins
题目链接:http://codeforces.com/gym/101201 /* * @Author: lyucheng * @Date: 2017-10-22 14:38:52 * @Last Mo ...
- 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)
A. Odd Palindrome 所有回文子串长度都是奇数等价于不存在长度为$2$的偶回文子串,即相邻两个字符都不同. #include<cstdio> #include<cstr ...
随机推荐
- scala函数进阶篇
1.求值策略scala里有两种求值策略Call By Value -先对函数实参求值,在函数体中用这个求出的参数值.Call By Name -先不对函数实参求值,而是函数实参每次在函数体内被用到时都 ...
- Linux mysqladmin 命令
mysqladmin命令可以用来设置或修改 MySQL 密码,常见用法如下: [root@localhost ~]$ mysqladmin -uroot password 'newPass' # 在无 ...
- OpenGL超级宝典总结(二)2D/3D笛卡尔坐标、坐标裁剪、纹理坐标、MVP转换等概念
如果你想把图形渲染在正确的位置上,那么坐标的设置就很重要了.在OpenGL中,与坐标相关的主要有笛卡尔坐标.坐标裁剪.纹理坐标.MVP(Model View Projection)转换. 1.笛卡尔坐 ...
- OpenStack三个节点icehouse
一.环境准备 1.架构 创建3台虚拟机,分别作为controll节点.network节点和compute1节点. Controller节点:1processor,2G memory,5G storag ...
- java基础---->java中字符编码问题(一)
这里面对java中的字符编码做一个总结,毕竟在项目中会经常遇到这个问题.爱不爱都可以,我怎样都依你,连借口我都帮你寻. 文件的编码格式 一.关于中文的二进制字节问题 public static Str ...
- PHP 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法
PHP 的异常处理.错误的抛出及回调函数等面向对象的错误处理方法: http://www.jb51.net/article/32498.htm http://www.cnblogs.com/hongf ...
- 有限制的最短路spfa+优先队列
poj1724 ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10751 Accepted: 3952 De ...
- 前端模拟(mock)接口数据(koa)
在前后端分离开发项目时,经常会有前后端进度不一致,可能前端界面开发已经完成,就等接口了,如果等接口出来再联调的话时间可能会来不及. 这个时候,前端就可以根据制定好的接口规范和接口文档来mock接口数据 ...
- HOJ 2317 Pimp My Ride(状态压缩DP)
Pimp My Ride My Tags (Edit) Source : TUD 2005 Time limit : 3 sec Memory limit : 64 M Submitted : 63, ...
- spring boot实战(第一篇)第一个案例
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] spring boot实战(第一篇)第一个案例 前言 写在前面的话 一直想将spring boot相关内容写成一个系列的 ...