ZOJ Monthly, January 2019
A: Little Sub and Pascal's Triangle
Solved.
题意:
求杨辉三角第n行奇数个数
思路:
薛聚聚说找规律,16说Lucas
答案是 $2^p \;\;p 为 n - 1 中 以2进制表示下1的个数$
证明
$Ans = \sum\limits_0^n C_n^i \;\%\; 2 = \sum\limits_0^n C_{\frac{n}{2}}^{\frac{i}{2}} \cdot C_{n\;\%\;2}^{i\;\%\;2}$
我们考虑 $C_{n \;\%\; 2}^{i \;\%\; 2}$ 一共有四种取值
$C_0^0 \;\; C_0^1\;\; C_1^0 \;\; C_1^1$
我们发现 只有 $C_0^1的值为0 其他三个值都为1$
那么我们再考虑$C_n^i 这个式子$
它通过卢卡斯定理分解 实际上可以写成
我们先假设
$i 以二进制表示为$
$a_1, a_2, \cdots a_k$
$n 以二进制表示为$
$b_1, b_2, \cdots b_k$
那么 $C_n^i = C_{b_1}^{a_1} \cdot C_{b_2}^{a_2} \cdots C_{b_k}^{a_k}$
那么我们发现,
要满足$C_n^i\;\%\; 2 = 1 \;\;$
$那么在b_y = 1的位置上,i在对应位置上取0或者1都可以$
在$b_y = 0 的位置上,i在对应位置的取值已经固定 是 0$
那么$i的取值一共有2^p p 为(n - 1)以2进制表示下1的个数$
为什么是$n - 1 \;\;因为杨辉三角是从第0行开始的$
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- ll n;
- int main()
- {
- int t;
- scanf("%d", &t);
- while(t--)
- {
- scanf("%lld", &n);
- n--;
- ll tmp = ;
- while(n)
- {
- if(n & ) tmp++;
- n >>= ;
- }
- ll ans = 1ll << tmp;
- printf("%lld\n", ans);
- }
- return ;
- }
B:Little Sub and his Geometry Problem
Solved.
题意:
一个点的权值定义为它到左下角所有点的曼哈顿距离
q次查询, 每次查询权值为c的点的个数
思路:
$给出的点沿着x轴正方向, y轴正方向都是严格单调递增的。$
$因此可以枚举x轴, 动态维护左下角点个数以及权值, 向右走的同时$
$将横坐标相同, 纵坐标<=当前位置的点假如, 向下走的时候将纵坐标相同给的点移除$
$当前权值为c时 ans++$
(薛聚聚:不会写题解啊)
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- typedef unsigned long long ull;
- const double eps = 1e-;
- const ll MOD = 1e9 + ;
- const ll INFLL = 0x3f3f3f3f3f3f3f3f;
- const int INF = 0x3f3f3f3f;
- const int maxn = 1e5 + ;
- int n, k;
- ll sum, cnt;
- ll sum_arr[maxn], cnt_arr[maxn];
- ll ans[];
- struct node {
- int x, y;
- node() {}
- node(int x, int y) :x(x), y(y) {}
- bool operator < (const node &other) const
- {
- return x == other.x ? y < other.y : x < other.x;
- }
- }P[maxn];
- ll solve(ll c)
- {
- cnt = sum = ;
- memset(sum_arr, , sizeof sum_arr);
- memset(cnt_arr, , sizeof cnt_arr);
- int index = ;
- int ans = ;
- int y = n;
- for (int x = ; x <= n; ++x)
- {
- while (index <= k && P[index].x <= x)
- {
- if (P[index].y <= y)
- {
- cnt++;
- sum += P[index].x + P[index].y;
- sum_arr[P[index].y] += P[index].x + P[index].y;
- cnt_arr[P[index].y]++;
- }
- ++index;
- }
- while ((x + y) * cnt - sum > c)
- {
- sum -= sum_arr[y];
- cnt -= cnt_arr[y];
- --y;
- }
- if ((x + y) * cnt - sum == c) ++ans;
- }
- return ans;
- }
- void RUN()
- {
- int t;
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d %d", &n, &k);
- for (int i = ; i <= k; ++i) scanf("%d %d", &P[i].x, &P[i].y);
- sort(P + , P + + k);
- int q;
- scanf("%d", &q);
- for (int i = ; i <= q; ++i)
- {
- ll c;
- scanf("%lld\n", &c);
- ans[i] = solve(c);
- }
- for (int i = ; i <= q; ++i) printf("%lld%c", ans[i], " \n"[i == q]);
- }
- }
- int main()
- {
- #ifdef LOCAL_JUDGE
- freopen("Text.txt", "r", stdin);
- #endif // LOCAL_JUDGE
- RUN();
- #ifdef LOCAL_JUDGE
- fclose(stdin);
- #endif // LOCAL_JUDGE
- return ;
- }
E:Little Sub and Mr.Potato's Math Problem
Solved.
题意:
给出n, k
将n个数按照字典序排序, k所在的位置为m
现在给出k, m 求最小的n
思路:
当k为10的整数倍, 那么它一定在第$log_{10^k}$
$随后统计当n=k的时候, 排在k前面的个数,和m比较, 判断是否合法$
$接着不断增加n, 统计每次增长排在k前面的个数, 随后输出n$
(薛聚聚:不会写题解啊)
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- typedef unsigned long long ull;
- const double eps = 1e-;
- const ll MOD = 1e9 + ;
- const ll INFLL = 0x3f3f3f3f3f3f3f3f;
- const int INF = 0x3f3f3f3f;
- const int maxn = 1e5 + ;
- ll k, m;
- int arr[maxn];
- ll pow_10[];
- void Init()
- {
- pow_10[] = ;
- for (int i = ; i <= ; ++i)
- {
- pow_10[i] = pow_10[i - ] * ;
- }
- }
- void solve()
- {
- ll num = ;
- for (int i = ;; ++i)
- {
- if (num > k) break;
- else if (num == k)
- {
- if (i == m)
- {
- printf("%lld\n", k);
- return;
- }
- else
- {
- puts("");
- return;
- }
- }
- num *= ;
- }
- int len = ;
- num = k;
- while (num)
- {
- arr[++len] = num % ;
- num /= ;
- }
- reverse(arr + , arr + + len);
- ll ans = ;
- num = ;
- for (int i = ; i <= len; ++i)
- {
- num = num * + arr[i];
- ans += num - pow_10[i - ];
- if (i != len) ++ans;
- }
- if (ans >= m)
- {
- puts("");
- return;
- }
- else if (ans == m - )
- {
- printf("%lld\n", k);
- return;
- }
- while ()
- {
- len++;
- num *= ;
- if (ans + num - pow_10[len - ] >= m - )
- {
- ans = pow_10[len - ] + m - ans - ;
- printf("%lld\n", ans);
- return;
- }
- ans += num - pow_10[len - ];
- }
- }
- void RUN()
- {
- Init();
- int t;
- scanf("%d", &t);
- while (t--)
- {
- scanf("%lld %lld", &k, &m);
- solve();
- }
- }
- int main()
- {
- #ifdef LOCAL_JUDGE
- freopen("Text.txt", "r", stdin);
- #endif // LOCAL_JUDGE
- RUN();
- #ifdef LOCAL_JUDGE
- fclose(stdin);
- #endif // LOCAL_JUDGE
- return ;
- }
F:Little Sub and a Game
Unsolved.
题意:
有两个玩家$A, B 刚开始有一个变量v = 0$
$A玩家有N个pair, B玩家有M个pair \;\; pair 为(x, y) A玩家N次操作,每次选择x_i 或者 y_i 来异或v B玩家有M次操作$
$A玩家先进行N次操作, B玩家再进行M次操作$
A玩家想让$v尽量大,B玩家想让v尽量小$
两个玩家都采用最优策略,求最后$v$的值
G:Little Sub and Tree
Solved.
题意:
给出一个无根树,选取$k个点对所有点进行编码$
按如下方式进行编码
$令选取的k个点为 s_1, s_2 \cdots s_k$
编出的码有$k位$
$对于u来说,第i位的编码为 s_i -> u的简单路径上的点的总数$
思路:
如果是一条链的话 那么取两端的一个就可以了
那么我们考虑一棵树中,如果某个节点的儿子对应的子树是一条链
那么这条链是可以被缩点成一个叶节点 而对答案没有影响
那么现在树就被我们简化成了 只有叶节点的子树
首先注意到,一棵子树内节点的区分和这棵子树外的点的选取是没有关系的
那么我们考虑 一个点对应的儿子当中,如果有$x个叶节点$
那么这x个节点要想被区分,就需要取$x - 1$ 个
再考虑一个点的儿子对应的子树,如果子树内都被区分了,那么合并起来也是被区分的
那么考虑选谁作为根
只要根不在链上就可以了,因为如果在链上会对缩点产生影响
- #include <bits/stdc++.h>
- using namespace std;
- #define N 100010
- int t, n, root, d[N], fa[N];
- vector <int> G1[N], G2[N], res;
- int pre(int u)
- {
- int id = -;
- int cnt = G1[u].size() - ;
- if (cnt == ) return u;
- for (auto v : G1[u]) if (v != fa[u])
- {
- fa[v] = u;
- id = pre(v);
- G2[u].push_back(id);
- }
- if (cnt == && u != root) return id;
- else return u;
- }
- void DFS(int u)
- {
- int need = ;
- for (auto v : G2[u]) if (v != fa[u] && !d[v])
- ++need;
- --need;
- for (auto v : G2[u]) if (v != fa[u])
- {
- fa[v] = u;
- if (!d[v] && need > )
- {
- --need;
- res.push_back(v);
- }
- DFS(v);
- }
- }
- int main()
- {
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d", &n);
- for (int i = ; i <= n; ++i)
- {
- G1[i].clear();
- G2[i].clear();
- d[i] = -;
- fa[i] = ;
- }
- res.clear();
- root = -;
- for (int i = , u, v; i < n; ++i)
- {
- scanf("%d%d", &u, &v);
- G1[u].push_back(v);
- G1[v].push_back(u);
- ++d[u]; ++d[v];
- }
- if (n == )
- {
- puts("1\n1");
- continue;
- }
- for (int i = ; i <= n; ++i) if (d[i] > )
- {
- root = i;
- break;
- }
- if(root == -)
- {
- int ans = ;
- for(int i = ; i <= n; ++i) if(d[i] == ) ans = i;
- printf("1\n%d\n", ans);
- continue;
- }
- pre(root);
- DFS(root);
- //puts("bug");
- //for (int i = 1; i <= n; ++i) printf("%d %d\n", i, fa[i]);
- //puts("bug");
- int k = res.size();
- printf("%d\n", k);
- for (int i = ; i < k; ++i) printf("%d%c", res[i], " \n"[i == k - ]);
- }
- return ;
- }
I:Little Sub and Isomorphism Sequences
Solved.
题意:
有一个$A[], 两种操作$
- $A_x -> y$
- 查询最长同构子串
思路:
考虑最长同构子串肯定会有重叠部分,那么两端出去的部分就是不同的部分
那么这个不同的部分让它长度为1即可,因为多余的长度是没有用的
那么题意就可以转化为 找一个最长的子串,使得两端相同即可
将数据离散化 开2e5个set维护每个数的位置
然后用数据结构 维护答案的最大值 即可
- #include <bits/stdc++.h>
- using namespace std;
- #define N 200010
- int t, n, m, a[N], b[N];
- struct qnode
- {
- int op, x, y;
- void scan()
- {
- scanf("%d", &op);
- if (op == )
- {
- scanf("%d%d", &x, &y);
- b[++b[]] = y;
- }
- }
- }q[N];
- set <int> s[N];
- namespace SEG
- {
- int a[N << ];
- void build(int id, int l, int r)
- {
- a[id] = -;
- if (l == r) return;
- int mid = (l + r) >> ;
- build(id << , l, mid);
- build(id << | , mid + , r);
- }
- void update(int id, int l, int r, int pos, int v)
- {
- if (l == r)
- {
- a[id] = v;
- return;
- }
- int mid = (l + r) >> ;
- if (pos <= mid) update(id << , l, mid, pos, v);
- else update(id << | , mid + , r, pos, v);
- a[id] = max(a[id << ], a[id << | ]);
- }
- }
- void Hash()
- {
- sort(b + , b + + b[]);
- b[] = unique(b + , b + + b[]) - b - ;
- for (int i = ; i <= n; ++i) a[i] = lower_bound(b + , b + + b[], a[i]) - b;
- for (int i = ; i <= m; ++i) if (q[i].op == ) q[i].y = lower_bound(b + , b + + b[], q[i].y) - b;
- }
- int main()
- {
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d%d", &n, &m);
- SEG::build(, , n + m);
- for (int i = ; i <= n + m; ++i) s[i].clear(); b[] = ;
- for (int i = ; i <= n; ++i) scanf("%d", a + i), b[++b[]] = a[i];
- for (int i = ; i <= m; ++i) q[i].scan(); Hash();
- for (int i = ; i <= n; ++i) s[a[i]].insert(i);
- for (int i = ; i <= n + m; ++i) if (s[i].size() >= )
- SEG::update(, , n + m, i, *s[i].rbegin() - *s[i].begin());
- for (int i = ; i <= m; ++i)
- {
- if (q[i].op == )
- {
- int v = a[q[i].x], x = q[i].x, y = q[i].y;
- s[v].erase(x);
- SEG::update(, , n + m, v, s[v].size() >= ? *s[v].rbegin() - *s[v].begin() : -);
- a[q[i].x] = y;
- v = y;
- s[v].insert(x);
- SEG::update(, , n + m, v, s[v].size() >= ? *s[v].rbegin() - *s[v].begin() : -);
- }
- else printf("%d\n", SEG::a[]);
- }
- }
- return ;
- }
ZOJ Monthly, January 2019的更多相关文章
- ZOJ Monthly, January 2019 Little Sub and his Geometry Problem 【推导 + 双指针】
传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5861 Little Sub and his Geometry Prob ...
- ZOJ Monthly, January 2019 Little Sub and Isomorphism Sequences 【离线离散化 + set + multiset】
传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5868 Little Sub and Isomorphism Seque ...
- ZOJ Monthly, January 2019 Little Sub and his Geometry Problem ZOJ4082(模拟 乱搞)
在一次被自己秀死... 飞机 题目: 给出N,K, Q; 给出一个N*N的矩阵 , 与K个特殊点 , 与Q次查询 , 每次查询给出一个C , 问 在这个N*N矩阵中 , 有多少的点是满足这样的一个关 ...
- ZOJ Monthly, January 2019 I Little Sub and Isomorphism Sequences(set 妙用) ZOJ4089
写这篇博客来证明自己的愚蠢 ...Orz 飞机 题意:给定你个数组,以及一些单点修改,以及询问,每次询问需要求得,最长的字串长度,它在其他位置存在同构 题解:经过一些奇思妙想后 ,你可以发现问题是传 ...
- ZOJ Monthly, January 2018 训练部分解题报告
A是水题,此处略去题解 B - PreSuffix ZOJ - 3995 (fail树+LCA) 给定多个字符串,每次询问查询两个字符串的一个后缀,该后缀必须是所有字符串中某个字符串的前缀,问该后缀最 ...
- matrix_2015_1 138 - ZOJ Monthly, January 2015
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3844 第一个,n个数,每次操作最大数和最小数都变成他们的差值,最后n个数相 ...
- ZOJ Monthly, January 2018
A 易知最优的方法是一次只拿一颗,石头数谁多谁赢,一样多后手赢 #include <map> #include <set> #include <ctime> #in ...
- ZOJ Monthly, January 2018 Solution
A - Candy Game 水. #include <bits/stdc++.h> using namespace std; #define N 1010 int t, n; int a ...
- ZOJ Monthly, January 2019-Little Sub and Pascal's Triangle
这个题的话,它每行奇数的个数等于该行行号,如果是0开始的,就该数的二进制中的1的个数,设为k,以它作为次数,2k就是了. #include <stdio.h> int main() { i ...
随机推荐
- Android中SurfaceView用法示例
SurfaceView在游戏开发中有着举足轻重的地位,它对于画面的控制有着更大的自由度(不像View要用handler来更新,关于View的),但这方面的参考资料并不是太多,能找到的例子都有点喧宾夺主 ...
- python2.0_s12_day19_前端结合后端展示客户咨询纪录
接下来就是将后台视图与前端页面结合起来了完成后台系统了.实现前端展示用户列表1.先在base.html代码中把模版中Dashboard下面的内容清空,如下: 具体删除哪些html代码,自己找吧.2.我 ...
- centos无法联网解决方法
1)进入 /etc/sysconfig/network-scripts/ 2)vi 或 vim 打开 ifcfg-eth0(不一定是eth0,这个自己判断了) 3)将 ONBOOT=no 改成 ONB ...
- 百度地图sdk问题 error inflating class com.baidu.mapapi.map.mapview
最近在封装开发中,有机会遇到问题还是记录下吧 但是其实都是一个原因 就是 初始化 在MyAplication onCreate()中加入 SDKInitializer.initialize(get ...
- Android SDK更新下载失败以及Studio首次安装取消自动下载SDK
这是因为,此时Android Studio会去获取 android sdk 组件信息,这个过程相当慢,还经常加载失败,导致Android Studio启动不起开. 解决办法: 不去获取android ...
- 浅谈Nutch插件机制(含开发实例)
plugin(插件)为nutch提供了一些功能强大的部件,举个例子,HtmlParser就是使用比较普遍的用来分析nutch抓取的html文件的插件. 为什么nutch要使用这样的plugin系统? ...
- 在centos命令行下安装软件
考虑到用linux纯命令行模式时,通常都是用作服务器,所以,一般主要是安装一个php.mysql.apache的集成环境和ftp服务器,在这里用xampp集成包即可解决所有问题,在这里说一下我自己的做 ...
- 【ecshop】如何解决DEPRECATED: PREG_REPLACE()报错
部署的ecshop 在高版本的PHP环境里边 ,访问 单个店铺时候会报错, 访问文件路径: http://www.test.com/supplier.php?suppId=5 类似这样的报错: D ...
- java框架---->Xstream的使用(一)
Xstream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称.今天我们就简单的学习一下xstream的用法. Xstream的简单实例 项目的结构如下,设计到三个类 ...
- 微信小程序5.2.2版本,找不着resource下exml皮肤
问题描述: egret engine 5.2.2 原来5.1.11好好的,一升级就跪了 新建一个项目,找不到皮肤... 已发到论坛问去了,现在只能手动复制皮肤到小游戏目录下... 解决方案: 卸载重新 ...