【AtCoder】AGC018
A - Getting Difference
我们肯定可以得到这些数的gcd,然后判断每个数减整数倍的gcd能否得到K
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,K;
int a[MAXN],g;
int gcd(int a,int b) {
return b == 0 ? a : gcd(b,a % b);
}
void Solve() {
read(N);read(K);
for(int i = 1 ; i <= N ; ++i) {
read(a[i]);
g = gcd(a[i],g);
}
for(int i = 1 ; i <= N ; ++i) {
if(a[i] >= K && (a[i] - K) % g == 0) {
puts("POSSIBLE");
return;
}
}
puts("IMPOSSIBLE");
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
B - Sports Festival
对于初始的喜爱度答案,如果我们不把含有个数最多的比赛ban掉,答案永远不会下降,所以我们试试一次次ban掉人数最多的比赛,取每次最小值
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,M;
int a[305][305],ans;
int cnt[305],pos[305];
bool vis[305];
void Solve() {
read(N);read(M);
for(int i = 1 ; i <= N ; ++i) {
for(int j = 1 ; j <= M ; ++j) {
read(a[i][j]);
}
}
for(int i = 1 ; i <= N ; ++i) {cnt[a[i][1]]++;pos[i] = 1;}
for(int i = 1 ; i <= M ; ++i) ans = max(ans,cnt[i]);
for(int k = 1 ; k < M ; ++k) {
int t = 1;
for(int j = 1 ; j <= M ; ++j) {
if(cnt[j] > cnt[t]) t = j;
}
vis[t] = 1;
for(int i = 1 ; i <= N ; ++i) {
cnt[a[i][pos[i]]]--;
while(vis[a[i][pos[i]]]) {++pos[i];}
cnt[a[i][pos[i]]]++;
}
int tmp = 0;
for(int j = 1 ; j <= M ; ++j) {
tmp = max(tmp,cnt[j]);
}
ans = min(ans,tmp);
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
C - Coins
把每个金币变成\((A_{i} - C_{i},B_{i} - C{i},0)\),然后总贡献加上所有\(C[i]\)
按照\(A[i] - B[i]\)排序,然后枚举一个中间点K,在K里面选\(B[i] - C[i]\)最大的Y个,在后面选\(A[i] - C[i]\)最大的\(X\)个,取最小值
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int X,Y,Z;
int64 A[MAXN],B[MAXN],C[MAXN],ans,f[MAXN],b[MAXN];
int id[MAXN];
multiset<int64> S;
void Solve() {
read(X);read(Y);read(Z);
for(int i = 1 ; i <= X + Y + Z ; ++i) {
read(A[i]);read(B[i]);read(C[i]);
ans += C[i];
A[i] -= C[i];B[i] -= C[i];
id[i] = i;
}
sort(id + 1,id + X + Y + Z + 1,[](int a,int b){return A[a] - B[a] < A[b] - B[b];});
int64 all = 0;
for(int i = 1 ; i <= X + Y + Z ; ++i) {
S.insert(B[id[i]]);
all += B[id[i]];
if(S.size() > Y) {
all -= *(S.begin());
S.erase(S.begin());
}
f[i] = all;
}
S.clear();all = 0;
for(int i = X + Y + Z ; i >= 1 ; --i) {
S.insert(A[id[i]]);
all += A[id[i]];
if(S.size() > X) {
all -= *(S.begin());
S.erase(S.begin());
}
b[i] = all;
}
int64 tmp = f[Y] + b[Y + 1];
for(int i = Y + 1; i <= Y + Z ; ++i) {
tmp = max(tmp,f[i] + b[i + 1]);
}
out(ans + tmp);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
D - Tree and Hamilton Path
熟练选手直接分析每条边能否取到最大贡献
每条边最大贡献是二倍的它断开后分成子树的较小的子树大小
如果是哈密顿回路,这个贡献显然可以通过求一个重心构造出来
哈密顿路分析一下,只和起点有关,和起点逐步往子树扩大的方向走,扩大到至少大小为\(\frac{N}{2}\)时所经过的边权和,就是我们要扣除的
如果有一条边可以把子树断成\(\frac{N}{2}\),那么减少的一定是这条边,否则其他情况都要经过这条边
否则求一个重心,找和重心相连的边最小的,其他情况一定包含一条和重心相连的边
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int to,next;int64 val;
}E[MAXN * 2];
int N,sumE,head[MAXN],siz[MAXN],son[MAXN],dep[MAXN],fa[MAXN];
int64 ans;
void add(int u,int v,int64 c) {
E[++sumE].to = v;
E[sumE].next = head[u];
E[sumE].val = c;
head[u] = sumE;
}
void dfs(int u) {
siz[u] = 1;
dep[u] = dep[fa[u]] + 1;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
fa[v] = u;
dfs(v);
siz[u] += siz[v];
son[u] = max(siz[v],son[u]);
ans += min(siz[v],N - siz[v]) * 2 * E[i].val;
}
}
son[u] = max(son[u],N - siz[u]);
}
void Solve() {
read(N);
int a,b;int64 c;
for(int i = 1 ; i < N ; ++i) {
read(a);read(b);read(c);
add(a,b,c);add(b,a,c);
}
dfs(1);
int t = 1;
for(int i = 2 ; i <= N ; ++i) {
if(son[i] < son[t] || (son[i] == son[t] && dep[i] > dep[t])) t = i;
}
if(N % 2 == 0 && son[t] == N / 2) {
for(int i = head[t] ; i ; i = E[i].next) {
if(E[i].to == fa[t]) ans -= E[i].val;
}
}
else {
int64 k = 0x7fffffff;
for(int i = head[t] ; i ; i = E[i].next) {
k = min(k,E[i].val);
}
ans -= k;
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
E - Sightseeing Plan
问网格图中某一矩形区域到顶点的和
居然是可以\(O(1)\)统计的,感觉非常长知识
具体怎么\(O(1)\)呢
问\((0,0)\)点到\((x,y)\)点的方案数,是\(\binom{x + y}{y}\)
记为\(W(x,y)\)
就是\(\sum_{i = 0}^{y}W(x,i) = W(x + 1,y)\)
就是在选\(x,i\)往右走一步,然后就一直往上走
\(\sum_{i = 0}^{x}\sum_{j = 0}^{y} W(i,j) = W(x + 1,y + 1) - 1\)
因为横竖同理,我们可以把每个都合成\(W(i + 1,y)\),少一个\(W(0,y)\),所以-1
这样我们求一个区域的值
\(\sum_{i = x_{1}}^{x_{2}}\sum_{j = y_{1}}^{y_{2}} W(x_{2} + 1,y_{2} + 1) - W(x_{1},y_{2} + 1) - W(x{2} + 1,y_{2}) + W(x_{1},y_{1})\)
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 1000005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
const int V = 2000005;
int X[7],Y[7],ans,fac[V + 5],invfac[V + 5];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void update(int &x,int y) {
x = inc(x,y);
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
int C(int n,int m) {
if(n < m) return 0;
return mul(fac[n],mul(invfac[m],invfac[n - m]));
}
int W(int x,int y) {
return C(x + y,x);
}
int way1(int x,int y) {
int s1 = x - X[2],s2 = x - X[1];
int t1 = y - Y[2],t2 = y - Y[1];
return inc(inc(W(s2 + 1,t2 + 1),W(s1,t1)),MOD - inc(W(s2 + 1,t1),W(s1,t2 + 1)));
}
int way2(int x,int y) {
int s1 = X[5] - x,s2 = X[6] - x;
int t1 = Y[5] - y,t2 = Y[6] - y;
return inc(inc(W(s2 + 1,t2 + 1),W(s1,t1)),MOD - inc(W(s2 + 1,t1),W(s1,t2 + 1)));
}
void Solve() {
fac[0] = 1;
for(int i = 1 ; i <= V ; ++i) fac[i] = mul(fac[i - 1],i);
invfac[V] = fpow(fac[V],MOD - 2);
for(int i = V - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
for(int i = 1 ; i <= 6 ; ++i) read(X[i]);
for(int i = 1 ; i <= 6 ; ++i) read(Y[i]);
for(int i = X[3] ; i <= X[4] ; ++i) {
update(ans,mul(MOD - (i + Y[3] - 1),mul(way1(i,Y[3] - 1),way2(i,Y[3]))));
update(ans,mul(i + Y[4],mul(way1(i,Y[4]),way2(i,Y[4] + 1))));
}
for(int j = Y[3] ; j <= Y[4] ; ++j) {
update(ans,mul(MOD - (X[3] - 1 + j),mul(way1(X[3] - 1,j),way2(X[3],j))));
update(ans,mul(j + X[4],mul(way1(X[4],j),way2(X[4] + 1,j))));
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
F - Two Trees
显然如果两个点在两棵树里儿子的奇偶性不同,一定误解
否则把两棵树建出一个无向图,然后如果两个点都有偶数个儿子,那么连一条边,再建一个点,把两棵树的树根都连在上面
求一个欧拉回路,那么如果从第一棵树到第二棵树,那么这个点就是1,否则就是-1
这样的道理是什么呢。。。可以从底向上归纳,显然两棵树的叶子点有两条边,出度和入度相等,给叶子上填上相应的数,然后叶子指向父亲的相当于把+1或-1贡献给父亲,从底向上归纳也行
在学完选修2-2之后,我可以把这个解释为,进行合情推理后,发现是对的= =
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define MAXN 100005
#define eps 1e-12
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N;
int A[MAXN],B[MAXN],s[MAXN][2],ans[MAXN];
struct node {
int to,next;
}E[MAXN * 10];
int head[MAXN * 2],sumE = 1;
bool vis[MAXN * 10];
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void euler_road(int u) {
for(int &i = head[u] ; i ; i = E[i].next) {
int w = i;
if(!vis[w]) {
vis[w] = vis[w ^ 1] = 1;
int v = E[w].to;
if(u != 2 * N + 1 && v != 2 * N + 1 && abs(u - v) == N) {
if(u < v) ans[u] = 1;
else ans[v] = -1;
}
euler_road(v);
}
}
}
void Solve() {
read(N);
for(int i = 1 ; i <= N ; ++i) {
read(A[i]);
if(A[i] != -1) {
add(i,A[i]);add(A[i],i);
s[A[i]][0]++;
}
else {
add(i,2 * N + 1);add(2 * N + 1,i);
}
}
for(int i = 1 ; i <= N ; ++i) {
read(B[i]);
if(B[i] != -1) {
add(i + N,B[i] + N);add(B[i] + N,i + N);
s[B[i]][1]++;
}
else {
add(i + N,2 * N + 1);add(2 * N + 1,i + N);
}
}
for(int i = 1 ; i <= N ; ++i) {
if((s[i][0] ^ s[i][1]) & 1) {
puts("IMPOSSIBLE");
return;
}
if(s[i][0] % 2 == 0) {
add(i,i + N);add(i + N,i);
}
}
puts("POSSIBLE");
euler_road(1);
for(int i = 1 ; i <= N ; ++i) {
out(ans[i]);space;
}
enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
【AtCoder】AGC018的更多相关文章
- 【AtCoder】ARC092 D - Two Sequences
[题目]AtCoder Regular Contest 092 D - Two Sequences [题意]给定n个数的数组A和数组B,求所有A[i]+B[j]的异或和(1<=i,j<=n ...
- 【Atcoder】CODE FESTIVAL 2017 qual A D - Four Coloring
[题意]给定h,w,d,要求构造矩阵h*w满足任意两个曼哈顿距离为d的点都不同色,染四色. [算法]结论+矩阵变换 [题解] 曼哈顿距离是一个立着的正方形,不方便处理.d=|xi-xj|+|yi-yj ...
- 【AtCoder】ARC 081 E - Don't Be a Subsequence
[题意]给定长度为n(<=2*10^5)的字符串,求最短的字典序最小的非子序列字符串. http://arc081.contest.atcoder.jp/tasks/arc081_c [算法]字 ...
- 【AtCoder】AGC022 F - Leftmost Ball 计数DP
[题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...
- 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT
[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...
- 【AtCoder】ARC067 F - Yakiniku Restaurants 单调栈+矩阵差分
[题目]F - Yakiniku Restaurants [题意]给定n和m,有n个饭店和m张票,给出Ai表示从饭店i到i+1的距离,给出矩阵B(i,j)表示在第i家饭店使用票j的收益,求任选起点和终 ...
- 【AtCoder】ARC095 E - Symmetric Grid 模拟
[题目]E - Symmetric Grid [题意]给定n*m的小写字母矩阵,求是否能通过若干行互换和列互换使得矩阵中心对称.n,m<=12. [算法]模拟 [题解]首先行列操作独立,如果已确 ...
- 【Atcoder】AGC022 C - Remainder Game 搜索
[题目]C - Remainder Game [题意]给定n个数字的序列A,每次可以选择一个数字k并选择一些数字对k取模,花费2^k的代价.要求最终变成序列B,求最小代价或无解.n<=50,0& ...
- 【Atcoder】AGC 020 B - Ice Rink Game 递推
[题意]n个人进行游戏,每轮只保留最大的a[i]倍数的人,最后一轮过后剩余2人,求最小和最大的n,或-1.n<=10^5. [算法]递推||二分 [题解]令L(i),R(i)表示第i轮过后的最小 ...
随机推荐
- jsp四大对象
发送参数: <a href="deal.jsp?id=1&user=用户&pwd=">处理页</a> 接收参数: <% String ...
- CSS魔法(三)浮动、相对定位、绝对定位
浮动 为何需要浮动? 浮动float最开始出现的意义是为了让文字环绕图片而已,但人们发现,如果想要三个块级元素并排显示,都给它们加个float来得会比较方便. 浮动问题? 为何要清除浮动? 很多情况下 ...
- Android studio 自动导入(全部)包 import
http://blog.csdn.net/buaaroid/article/details/44979629 1 Android studio 只有import单个包的快捷键:Alt+Enter.没有 ...
- luogu P1445 [Violet]嘤F♂A
博主决定更博文啦 这道题一开始没什么思路啊qwq 要求 \(\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}\) 的正整数解总数 首先通分,得 \[\frac{x+y}{xy} ...
- mysql 原理 ~ binlog
一 简介:我们会持续对binlog进行分析,但是不深入代码二 版本 5.6 格式 GTID和传统格式 传统格式 一 binlog针对具体事务注意点-1 1 u ...
- Adjoint of SE(3)
以前看的书都提到 SE(3) 和 se(3) 的 Adjoint,但是并没有讲这个东西是干什么用的,只是给了一堆性质.这东西来自群论. 参考 Lie Groups for 2D and 3D Tran ...
- python 退出程序的方式
python程序退出方式[sys.exit() os._exit() os.kill() os.popen(...)] 知乎说明 http://www.zhihu.com/question/21187 ...
- python 历险记(三)— python 的常用文件操作
目录 前言 文件 什么是文件? 如何在 python 中打开文件? python 文件对象有哪些属性? 如何读文件? read() readline() 如何写文件? 如何操作文件和目录? 强大的 o ...
- 初识CPU卡、SAM卡/CPU卡简介、SAM卡简介 【转】
初识CPU卡.SAM卡/CPU卡简介.SAM卡简介 IC卡按照接口方式可分为接触式卡.非接触式卡.复合卡:按器件技术可分为非加密存储卡.加密存储卡和CPU卡. 加密存储卡是对持卡人的认证,只有输入正确 ...
- 006_netstat中state详解
TCP三次握手的过程如下: 主动连接端发送一个SYN包给被动连接端: 被动连接端收到SYN包后,发送一个带ACK和SYN标志的包给主动连接端: 主动连接端发送一个带ACK标志的包给被动连接端,握手动作 ...