NewOJ周赛于2022年3月19日正式开始,比赛时间为每周六晚19:00-22:00。

比赛链接:http://oj.ecustacm.cn/contest.php?cid=1016

A xyz

题意: x , y , z x,y,z x,y,z为三个正整数,给定 7 7 7个数表示 x , y , z , x + y , x + z , y + z , x + y + z x,y,z,x+y,x+z,y+z,x+y+z x,y,z,x+y,x+z,y+z,x+y+z的某种排列,求 x , y , z x,y,z x,y,z。

Tag: 思维题

难度:

来源: U S A C O 2020 D e c USACO\ 2020\ Dec USACO 2020 Dec

思路: 由于 x , y , z x,y,z x,y,z都是正整数,所以最小的两个数字分别对应着 x x x和 y y y,所以只需要排个序就求出了 x x x和 y y y。而 7 7 7个数字中的最大值一定对应着 x + y + z x+y+z x+y+z,所以 z z z可以利用最大值减去 x x x和 y y y求得。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{int a[7];for(int i = 0; i < 7; i++)cin >> a[i];sort(a, a + 7);     //排序//最小的数字a[0]、a[1]对应着x和y//最大的数字a[6]对应着x+y+zcout<<a[0]<<" "<<a[1]<<" "<<a[6] - a[0] - a[1]<<endl;return 0;
}

B Pow Set

题意: 求集合 S = { a b ∣ 2 ≤ a ≤ n , 2 ≤ b ≤ m } S=\{a^b|2\le a \le n,2\le b \le m\} S={ab∣2≤a≤n,2≤b≤m}元素个数。

Tag: 数论、哈希

难度: ☆☆☆

来源: 欧拉计划 P r o b l e m 29 Problem\ 29 Problem 29 改编

思路1: 对于两个幂而言,如果 a 1 b 1 = a 2 b 2 a_1^{b_1}=a_2^{b_2} a1b1​​=a2b2​​,则它们的因式分解后的素因子表示是相同的。因此可以最开始就处理出 [ 2 , 500 ] [2,500] [2,500]每个数字的因式分解,然后对于每个幂 a b a^b ab而言,只需要对 a a a的因式分解的基础上,所有指数乘上 b b b即可。

我们可以用 p a i r < i n t , i n t > x pair<int,int>x pair<int,int>x表示 x . f i r s t x . s e c o n d x.first^{x.second} x.firstx.second,这样对于每个数字的因式分解可以用 v e c t o r < p a i r < i n t , i n t > > vector<pair<int,int> > vector<pair<int,int>>表示。然后再用 S T L STL STL中的集合set去重。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int>Pair;///对x进行因式分解
vector<Pair> factorization(int x)
{vector<Pair> ans;for(int i = 2; i * i <= x; i++)if(x % i == 0)///i是x的因子{int num = 0;while(x % i == 0)++num, x /= i;///统计i的幂ans.push_back(make_pair(i, num));///存入ans}///最后可能会有一个大于根号x的素因子if(x != 1)ans.push_back(make_pair(x, 1));return ans;
}///all_factor[i]表示i的唯一分解
vector<Pair>all_factor[510];///存储集合
set<vector<Pair>>S;///把a^b以唯一分解的形式塞入集合S
void insert_pow(int a, int b)
{vector<Pair>ans;///遍历a的唯一分解for(auto x : all_factor[a])ans.push_back(make_pair(x.first, x.second * b));S.insert(ans);
}int main()
{///预处理出2到500每个数字的唯一分解表示for(int i = 2; i <= 500; i++)all_factor[i] = factorization(i);int n, m;cin >> n >> m;for(int a = 2; a <= n; a++)for(int b = 2; b <= m; b++)insert_pow(a, b);cout<<S.size()<<endl;return 0;
}

思路2: 由于这里要求的相当于大数去重,我们无法直接求出大数,但是可以间接利用哈希的思路来判断是否重复。

比如我们利用一个模数 m m m,计算出每一个 a b % m a^b\%m ab%m,对集合 a b % m {a^b\%m} ab%m去重即可。

但是可能会存在两个不同的幂, a 1 b 1 ≠ a 2 b 2 a_1^{b_1}\ne a_2^{b_2} a1b1​​​=a2b2​​,但是对 m m m取模之后相同。

为了避免这种情况,可以采用两个模数 m 1 , m 2 m_1,m_2 m1​,m2​,那么对于一个幂 a b a^b ab,我们用二元组 < a b % m 1 , a b % m 2 > <a^b\%m_1,a^b\%m_2> <ab%m1​,ab%m2​>表示。只要二元组相同,认为幂是相同的。

一般来说常用的 m 1 m_1 m1​和 m 2 m_2 m2​可以取 1 0 9 + 7 10^9+7 109+7和 1 0 9 + 9 10^9+9 109+9,这是由于取孪生质数出错的概率较低。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int>Pair;///快速幂模板
int ksm(int a, int b, int m)
{int ans = 1;while(b){if(b & 1)ans = (ll)ans * a % m;b >>= 1;a = (ll)a * a % m;}return ans;
}///存储哈希二元组
set<Pair>S;int main()
{int MOD1 = 1e9 + 7;int MOD2 = 1e9 + 9;int n, m;cin >> n >> m;for(int a = 2; a <= n; a++)for(int b = 2; b <= m; b++)S.insert(make_pair(ksm(a, b, MOD1), ksm(a, b, MOD2)));cout<<S.size()<<endl;return 0;
}

C Sum of Interval

题意: 给定长度为 n n n的数组 a a a,求 ∑ l = 1 n ∑ r = l n ∑ i = l r a [ i ] \sum_{l=1}^n\sum_{r=l}^n\sum_{i=l}^{r}a[i] ∑l=1n​∑r=ln​∑i=lr​a[i]

Tag: 前缀和、思维题

难度: ☆☆

来源: 51 n o d 2651 51nod\ 2651 51nod 2651

思路: 70 − 80 70-80 70−80分做法: 最后一个求和变成前缀和 s u m [ r ] − s u m [ l − 1 ] sum[r]-sum[l-1] sum[r]−sum[l−1]。

100 100 100分做法: 反向思考,考虑每一个 a [ i ] a[i] a[i]出现的次数,即 a [ i ] a[i] a[i]在哪些区间 [ l , r ] [l,r] [l,r]中出现,相当于求 1 ≤ l ≤ i ≤ r ≤ n 1\le l \le i \le r\le n 1≤l≤i≤r≤n的 < l , r > <l,r> <l,r>对的数量。有 i − 1 i-1 i−1个数字在 a [ i ] a[i] a[i]左边, n − i n-i n−i个数字在 a [ i ] a[i] a[i]右边,对于 a [ i ] a[i] a[i]而言,出现区间的数量为 ( i − 1 + 1 ) ∗ ( n − i + 1 ) (i-1+1)*(n-i+1) (i−1+1)∗(n−i+1)。

所以,最终的答案 a n s = ∑ i = 1 n a [ i ] ∗ ( i − 1 + 1 ) ∗ ( n − i + 1 ) ans=\sum_{i=1}^na[i]*(i-1+1)*(n-i+1) ans=∑i=1n​a[i]∗(i−1+1)∗(n−i+1)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
ll n, x, ans;
int main()
{cin >> n;for(int i = 1; i <= n; i++){cin >> x;ans += x * i * (n - i + 1);}cout<<ans<<endl;return 0;
}

D 极差

题意: 询问固定数组的区间极差

Tag: S T ST ST表,线段树

难度: ☆☆☆

来源: U S A C O 2007 J a n USACO\ 2007\ Jan USACO 2007 Jan

思路: 由于对原数组不进行修改,可以直接用 S T ST ST表求区间最大值、区间最小值。也可以使用线段树进行查询区间最值。不带修改的线段树写起来也很简便。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 10;
int tree_max[maxn << 2];
int tree_min[maxn << 2];
int a[maxn];///建树
void build(int o, int l, int r)
{if(l == r){tree_max[o] = tree_min[o] = a[l];return;}int mid = (l + r) >> 1;///递归建立左子树和右子树build(o << 1, l, mid);build(o << 1 | 1, mid + 1, r);///回溯时更新父节点权值tree_max[o] = max(tree_max[o<<1], tree_max[o<<1|1]);tree_min[o] = min(tree_min[o<<1], tree_min[o<<1|1]);
}int ans_max, ans_min;
///查询区间[L, R]的最值
void query(int o, int l, int r, int L, int R)
{///递归出口 [l,r]属于[L,R]if(L <= l && R >= r){ans_max = max(ans_max, tree_max[o]);ans_min = min(ans_min, tree_min[o]);return;}///递归处理左右子树即可int mid = (l + r) >> 1;if(L <= mid)query(o << 1, l, mid, L, R);if(R > mid)query(o << 1 | 1, mid + 1, r, L, R);
}int main()
{int n, m;scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++)scanf("%d", &a[i]);build(1, 1, n);while(m--){int l, r;scanf("%d%d", &l, &r);ans_max = 0;ans_min = 1e9 + 7;query(1, 1, n, l, r);printf("%d\n", ans_max - ans_min);}return 0;
}

E 比赛

题意: n n n位选手进行 m m m场比赛,每场比赛两位选手均有可能获胜,赢的最多的人,胜利次数最小是多少。

Tag: 二分答案、网络流

难度: ☆☆☆☆

来源: P O I 2005 POI\ 2005 POI 2005

思路: 这道题目属于典型的最大值最小化,可以考虑使用二分答案进行求解。假设当前赢的最多的人胜利次数为 x x x。

将问题转换成判定性问题:每个选手最多赢 x x x场,能否完成 m m m场比赛。

在 m m m场比赛中,每场比赛最多只有一个人胜利。在上述约束“每个选手最多赢 x x x场”下,给每场比赛匹配一个胜利的人。

如果我们把比赛和人都看做点的话,用流量表示胜利次数,则图可以很容易建立:

  • 每场比赛只允许一个人胜利:源点 S S S向比赛连边,流量为 1 1 1
  • 每场比赛对应两个人:比赛向两位选手分别连边,流量为 1 1 1
  • 每个选手最多赢 x x x场:选手向汇点 T T T连边,流量为 x x x

如果从 S S S到 T T T的最大流等于 m m m,说明m场比赛在上述约束下,都可以成功匹配,至此,判定性问题解决。

回到最大值最小化问题,利用二分答案模板,由于本题求最小值,因此满足条件时,说明 x x x是合法的,最终的答案还可能更小,更新的是右端点 r i g h t right right。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e4 + 10;
const int INF = 1e9 + 7;
int n, m;
int a[10010], b[10010];
struct edge
{int u, v, c, f;edge(int u, int v, int c, int f):u(u), v(v), c(c), f(f){}
};
vector<edge>e;
vector<int>G[maxn];int level[maxn];//BFS分层,表示每个点的层数
int iter[maxn];//当前弧优化void init(int n)
{for(int i = 0; i <= n; i++)G[i].clear();e.clear();
}
void addedge(int u, int v, int c)
{e.push_back(edge(u, v, c, 0));e.push_back(edge(v, u, 0, 0));int m = e.size();G[u].push_back(m - 2);G[v].push_back(m - 1);
}
void BFS(int s)//预处理出level数组
//直接BFS到每个点
{memset(level, -1, sizeof(level));queue<int>q;level[s] = 0;q.push(s);while(!q.empty()){int u = q.front();q.pop();for(int v = 0; v < G[u].size(); v++){edge& now = e[G[u][v]];if(now.c > now.f && level[now.v] < 0){level[now.v] = level[u] + 1;q.push(now.v);}}}
}
int dfs(int u, int t, int f)//DFS寻找增广路
{if(u == t)return f;//已经到达源点,返回流量ffor(int &v = iter[u]; v < G[u].size(); v++)//这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历//在每次找增广路的时候,数组要清空{edge &now = e[G[u][v]];if(now.c - now.f > 0 && level[u] < level[now.v])//now.c - now.f > 0表示这条路还未满//level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想{int d = dfs(now.v, t, min(f, now.c - now.f));if(d > 0){now.f += d;//正向边流量加de[G[u][v] ^ 1].f -= d;//反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到return d;}}}return 0;
}
int Maxflow(int s, int t)
{int flow = 0;for(;;){BFS(s);if(level[t] < 0)return flow;//残余网络中到达不了t,增广路不存在memset(iter, 0, sizeof(iter));//清空当前弧数组int f;//记录增广路的可增加的流量while((f = dfs(s, t, INF)) > 0)flow += f;}return flow;
}///赢最多的人次数为mid,判断是否合法
bool check(int mid)
{int S = 0, T = n + m + 1;init(T);///源点S向每场比赛连边,流量为1for(int i = 1; i <= m; i++)addedge(S, i, 1);///每场比赛分别向两个选手连边for(int i = 1; i <= m; i++)addedge(i, a[i] + m, 1), addedge(i, b[i] + m, 1);///每个选手向汇点T连边,流量为mid,表示每个人最多赢mid次for(int i = 1; i <= n; i++)addedge(i + m, T, mid);///满流则说明每场比赛在当前约束下,都可以正常匹配,说明允许每个人最多赢mid次return Maxflow(S, T) == m;
}
int main()
{cin >> n >> m;for(int i = 1; i <= m; i++)cin >> a[i] >> b[i];int left = 1, right = m, ans;while(left <= right){int mid = (left + right) >> 1;if(check(mid)){///合法的话,说明可以继续更小ans = mid;right = mid - 1;}elseleft = mid + 1;}cout<<ans<<endl;return 0;
}

NewOJ Week 2题解相关推荐

  1. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  2. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  3. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  4. [JS]题解 | #岛屿数量#

    题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...

  5. [JS] 题解:提取不重复的整数

    题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...

  6. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

  7. [洛谷1383]高级打字机 题解

    题解 这道题一看就珂以用主席树啊 这是一道神奇的题目,那么我们先敲一个主席树,然后维护一个数组len,表示下一次应该在len + 1插入, 之后对于T操作,在上一个版本的len + 1上直接执行插入 ...

  8. luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...

  9. 【题解搬运】PAT_L1-009 N个数求和

    从我原来的博客上搬运.原先blog作废. (伪)水题+1,旨在继续摸清这个blog(囧 题目 就是求N个数字的和.麻烦的是,这些数字是以有理数"分子/分母"的形式给出的,你输出的和 ...

最新文章

  1. 零起点学算法03——超简单模仿算术题
  2. wxWidgets 富文本编辑器示例
  3. COJ 1006 树上操作
  4. ssis mysql to server_SSIS:将表从MySQL复制到SQL Server 2008
  5. pagerAdapter 与FragmentPagerAdapter的区别
  6. 【转载】几个比较靠谱的即时通讯软件
  7. MySQL怎么查游戏内邮件附件_怎么查询游戏mysql账号密码
  8. dpkg命令_Linux常用命令大全(二)
  9. ./configure:command not found 解决方法
  10. 洛谷 题解 P1757 【通天之分组背包】
  11. JAVA分布式架构设计实例
  12. 微信公众号全局返回码
  13. C++打印九九乘法表
  14. linux 查看内网IP和外网IP
  15. Grafana 汉化
  16. JDK8新特性知识点总结
  17. 什么是梯度?为什么梯度的方向总是指向函数值增大的方向?
  18. c++裸函数naked解析
  19. Baxter robot 碰撞检测相关问题集合(自己学习用)
  20. 這些食物絕對不能放隔夜(圖)

热门文章

  1. 计算机导论黄国兴电子版第三版,计算机导论黄国兴
  2. python输出两个整数的最大公约数和最小公倍数_编程实现输入两个整数,输出其最大公约数和最小公倍数。...
  3. 惠普G80服务器做阵列和安装redhat系统
  4. 静态分析 第三课 Data Flow Analysis(1)
  5. 第一本书 第九章 使用对象吃货联盟
  6. 数据结构与算法 学习笔记(上)
  7. JDBC通过Statement执行查询操作
  8. android service什么时候销毁,阳光沙滩-android 通过AppWidgetProvider 启动的Service会自动销毁问题...
  9. 数学:确定性的丧失---第八章 不合逻辑的发展:天堂之门
  10. c语言设计实验报告答案,武汉理工大学《C语言程序设计》实验报告答案