CF1220

A

one和zero特的字母分别是'n'和'z'

输出他们的数量即可

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define min std::min
#define max std::max
const int N = 3e5 + 3;
char s[N];
int sum[N];
int n;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int main(){
n = read();
scanf("%s",s + 1);
for(int i = 1;i <= n;++i) sum[s[i]]++;
int cnt = 0;
while(sum['n']){
cnt++;
printf("1 ");
sum['n']--;
}
while(sum['z']){
printf("0 ");
sum['z']--;
}
return 0;
}

B

给你一个\(n * n\)的矩阵,第\((i,j)\)个位置表示\(a_i \times a_j\)(对角线为\(0\))

求数组\(a\)

对于任意三个\((i,j,k)\)

我们有\(a_i^2 = \frac{a_i \times a_j \times a_k \times a_j}{a_j \times a_k}\)

所以按照这种方式可以求出每个\(a_i^2\),最后开根号即可

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define min std::min
#define max std::max
const int N = 1005;
LL a[N][N];
LL ans[N];
int n,m;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int main(){
n = read();
for(int i = 1;i <= n;++i) for(int j = 1;j <= n;++j) a[i][j] = read();
for(int i = 1;i <= n;++i){
int x = 0,y = 0;
if(i <= n - 2) x = i + 1,y = i + 2;
else if(i == n - 1) x = 1,y = n;
else x = 1,y = 2;
ans[i] = a[i][x] * a[i][y] / a[x][y];
}
for(int i = 1;i <= n;++i) printf("%.0lf ",sqrt((double)ans[i]));
return 0;
}

C

给定一个字符串\(s\)

游戏规则

当前在\([l,r]\)每次只能扩展到\([l',r']\)使得\(l' \le l,r \ge r\)且\(s[l',r']\)的字典序比\(s[l,r]\)要小,不能走的时候对方获胜

对于每个\(i\),求出当初始状态为\([i,i]\)时,先手是否必胜

很明显,只要存在\(s[l', r']\)满足条件,那么先手一定可以移动到最优解,那么只需要判断是否存在比现在这个状态字典序更小的状态存在即可

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define min std::min
#define max std::max
const int N = 1e6 + 3;
char s[N];
int sum[27][N];
int n;
int ans = 0x3f3f3f3f;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int main(){
scanf("%s",s + 1);
n = strlen(s + 1);
for(int i = n;i >= 1;--i){
for(int j = 0;j < 26;++j) sum[j][i] = sum[j][i + 1];
sum[s[i] - 'a'][i]++;
}
for(int i = 1;i <= n;++i){
bool flag = 0;
for(int j = s[i] - 'a' - 1;j >= 0;--j) if(sum[j][1] - sum[j][i] > 0) flag = 1;
if(!flag)
printf("Mike\n");
else printf("Ann\n"); }
return 0;
}

D

题目大意:给定一个正整数集合\(B\)。

让所有整数都为一张无向图中的顶点。\(i, j\)之间有边,当且仅当\(\left| i - j\right| \in B\)

现在要从\(B\)中删去最少的元素,使得这张无向图变成二分图

首先二分图的定义:不存在奇环

首先对于\(B\)中的元素\(x,y\)

\[\dfrac{lcm(x,y)}{x} + \frac{lcm(x,y)}{y}
\]

这个式子如果是奇数,那么存在奇环

我们分类讨论一下

若\(x,y\)是奇数

那么上面的式子一定是偶数

若\(x,y\)是一奇一偶,那么上面的式子是偶数

如果\(x,y\)是偶数

那么我们就设\(x = 2x' ,y = 2y'\)

发现就变成了一个子问题,直到出现一奇一偶或者全是奇数的情况就能判断他们能否共存

发现第三种情况的本质就是这两个数的二进制末尾0个数是否相同

(因为不断除二,判断奇偶性)

所以我们由二推多,末尾0个数相同的可以共存,所以最终答案就是\(n\)减去最多的一类

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define min std::min
#define max std::max
const int N = 5e5 + 3;
inline LL read(){
LL v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int n;
LL a[N];
LL num[N];
int cnt[N];
int main(){
n = read();
for(int i = 1;i <= n;++i) a[i] = read();
for(int i = 1;i <= n;++i){
LL x = a[i];
while((x & 1) == 0){
num[i]++;
x >>= 1;
}
cnt[num[i]]++;
}
int sum = 0,id = 0x3f3f3f3f;
for(int i = 0;i <= n;++i)
if(sum < cnt[num[i]]) sum = cnt[num[i]],id = num[i];
printf("%d\n",n - sum);
for(int i = 1;i <= n;++i){
if(num[i] != id) printf("%lld ",a[i]);
}
return 0;
}

E

题目大意

给定一个无向图,点有点权(非负),不能连续通过同一条边,一条从\(S\)出发的路径使得点权和最大(重复经过算一次)

(这里的环定义貌似有点奇特,图中的非黄色点都属于环)

首先,如果存在环,那么这和环上的点我们都是可以经过的

所以我们只需要考虑不在换上的点的贡献,之后发现如果我们走进了这种点

就再也不能回头

比如说图中黄色的点,我们一旦从环上走了进去,就只能向下走

我们一定先去把换上的点先跑一边,之后再剩下的点没被经过的点中选一条向下点权和最大的点即可

考虑如何去实现这个过程,首先找环

可以使用类拓扑排序找到环,然后可以证明,环上的点都是可以算进贡献的

是不是我们再寻找一条最大路径就好了

但是注意我们只是讨论了起点再环上的情况

若起点不在环上,最优解可能是这个样子

蓝色部分

也就是说,\(S\)到环上的路径也成为了恒有贡献的部分

(即使最优解在\(S\)的下边我们也可以上去再下来)

所以把这一块也标记一下就好了

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define min std::min
#define max std::max
const int N = 5e5 + 3;
LL w[N];
struct edge{
int to;
int nxt;
}e[N << 1];
LL f[N];
int n,m;
LL ans,res;
int s;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int tot,cnt;
int head[N],d[N];
bool used[N],flag[N];LL dp[N];
int fa[N];
inline void add(int x,int y){
e[++tot].to = y;
e[tot].nxt = head[x];
head[x] = tot;
}
inline void pre(){
flag[s] = 1;
std::queue <int> q;
for(int i = 1;i <= n;++i) if(d[i] == 1) q.push(i),f[i] = w[i];
while(!q.empty()){
int k = q.front();used[k] = 1;q.pop();
for(int i = head[k];i;i = e[i].nxt){
int y = e[i].to;
if(used[y]) continue;
f[y] = max(f[y],f[k] + w[y]);
flag[y] |= flag[k];
d[y]--;
if(d[y] == 1) q.push(y);
}
}
}
inline void dfs(int x,int f){
for(int i = head[x];i;i = e[i].nxt){
int y = e[i].to;
if(y == f) continue;
dfs(y,x);
dp[x] = max(dp[x],dp[y]);
}
dp[x] += w[x];
}
int main(){
n = read(),m = read();
for(int i = 1;i <= n;++i) w[i] = read();
for(int i = 1;i <= m;++i){
int x = read(),y = read();
add(x,y);
add(y,x);
d[x]++,d[y]++;
}
s = read();
if(m == n - 1){
dfs(s,0);
printf("%lld\n",dp[s]);
return 0;
}
pre();
for(int i = 1;i <= n;++i) if(flag[i]) ans += w[i],f[i] = 0;
for(int i = 1;i <= n;++i){
if(flag[i]) continue;
if(used[i]) res = max(res,f[i]);
else ans += w[i];
}
printf("%lld\n",ans + res);
return 0;
}
 

CF1220的更多相关文章

  1. CF1220题解

    D 考虑从0出发,两个属于集合的元素\(x,y\) \(ax=by\),则形成奇环需要\(a+b\equiv 1(\% 2)\) 需要无奇环,\(\frac{lcm(x,y)}{x}+\frac{lc ...

随机推荐

  1. Directx11教程(34) 纹理映射(4)

    原文:Directx11教程(34) 纹理映射(4)     本篇教程中,我们尝试在myTutorialD3D_27中改变采样状态描述符的各种设置,看纹理贴图的方式有什么变化. 原始的代码是:     ...

  2. Directx11教程(19) 画一个简单的地形

    原文:Directx11教程(19) 画一个简单的地形       通常我们在xz平面定义一个二维的网格,然后y的值根据一定的函数计算得到,比如正弦.余弦函数的组合等等,可以得到一个看似不错的地形或者 ...

  3. iOS 9 新特性之实现 3D Touch

    http://www.cocoachina.com/ios/20151027/13812.html 10月19号,周末,起床去吃早餐,吃完回来顺便去沃尔玛逛逛,把晚上的菜给买了,逛着逛着就来到了卖苹果 ...

  4. Python 局部变量转为全局变量

  5. vagrant 安装 ubuntu

    安装版本: ubuntu  trusty64(14.04) step1: 安装vagrant,vbox step2: 下载box文件(官网http://www.vagrantbox.es/) http ...

  6. hdu4325 线段树 成段更新

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #def ...

  7. shell学习(16)- 压缩和解压缩命令tar和zip

    tar命令 [root@Linux ~]# tar [-cxtzjvfpPN] 文件与目录 .... 参数: -c :建立一个压缩文件的参数指令(create 的意思): -x :解开一个压缩文件的参 ...

  8. Java练习 SDUT-1149_计算题

    计算题 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 一个简单的计算,你需要计算f(m,n),其定义如下: 当m=1时 ...

  9. 云原生生态周报 Vol. 5 | etcd性能知多少

    业界要闻 1 Azure Red Hat OpenShift已经GA.在刚刚结束的Red Hat Summit 2019上,Azure Red Hat OpenShift正式宣布GA,这是一个微软和红 ...

  10. @atcoder - Japanese Student Championship 2019 Qualification - E@ Card Collector

    目录 @description@ @solution@ @accepted code@ @details@ @description@ N 个卡片放在 H*W 的方格图上,第 i 张卡片的权值为 Ai ...