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. C++之以分隔符的形式获取字符串

    void CConvert::Split(const std::string& src, const std::string& separator, std::vector<st ...

  2. Java练习 SDUT-3339_计算长方形的周长和面积(类和对象)

    计算长方形的周长和面积(类和对象) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 设计一个长方形类Rect,计算长方形 ...

  3. VelocityTracker监控速度!!!

    用来追踪触摸事件(flinging事件和其他手势事件)的速率.用obtain()函数来获得类的实例,用addMovement(MotionEvent)函数将motion event加入到Velocit ...

  4. MyBatis动态SQL(一)

    MyBatis 的强大特性之一便是它的动态 SQL.动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似.在 MyBatis 之前的版本中,有很多元素需要花时间了解.MyBatis 3 ...

  5. spring-jpa通过自定义sql执行修改碰到的问题

    在编写自定义SQL的时候需要注意 @Query 注解只能用来查询,想要进行添加.修改和删除操作需要配合 @Modifying 注解一同使用 @Modifying @Query("update ...

  6. mysql带有子查询的like查询

    SELECT * FROM by_app_categories WHERE c_name LIKE CONCAT('%', (SELECT `name` FROM b_catelist WHERE t ...

  7. 一个 PHP 面试题

    一个 PHP 面试题 $i = 0; $j =1; if ($i = 5 || ($j =6)) {echo $i,$j++;} 拿来当面试题不错. 实际并不会这样用,但这个题可以考基础.

  8. oracle函数 months_between(d1,d2)

    [功能]:返回日期d1到日期d2之间的月数. [参数]:d1,d2 日期型 [返回]:数字 如果d1>d2,则返回正数 如果d1<d2,则返回负数 [示例] select sysdate, ...

  9. Libev源码分析08:Libev中的信号监视器

    Libev中的信号监视器,用于监控信号的发生,因信号是异步的,所以Libev的处理方式是尽量的将异步信号同步化.异步信号的同步化方法主要有:signalfd.eventfd.pipe.sigwaiti ...

  10. SLS机器学习最佳实战:日志聚类+异常告警

    1.手中的锤子都有啥? 围绕日志,挖掘其中更大价值,一直是我们团队所关注.在原有日志实时查询基础上,今年SLS在DevOps领域完善了如下功能: 上下文查询 实时Tail和智能聚类,以提高问题调查效率 ...