Codeforces Round #196 (Div. 1) 题解
(CF唯一不好的地方就是时差……不过还好没去考,考的话就等着滚回Div. 2了……)
A - Quiz
裸的贪心,不过要用矩阵乘法优化或者直接推通式然后快速幂。不过本傻叉做的时候脑子一片混乱,导致WA+TLE若干次,而且还做了很久(半小时)……
#include <cstdio>
const int MOD = 1000000000+9;
int ans,n,m,k;
int power(long long x,int k)
{
int res = 1;
for (;k;k >>= 1,x = x*x%MOD)
if (k&1) res = 1ll*res*x%MOD;
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
#endif
scanf("%d%d%d",&n,&m,&k);
long long i;
// for (i = 0; 1; i += k) {
// if (n - i <= m) break;
// if (m >= k - 1) {
// m -= (k - 1);
// (ans += k - 1)%=MOD;
// }else {
// (ans += m)%=MOD;
// printf("%d\n",ans);
// return 0;
// }
// }
i = 1ll*(n - m)*k;
//printf("%d\n",i);
if (i > n) {
printf("%d\n",m);
return 0;
}
ans = 1ll*(n - m)*(k - 1)%MOD;
int ans1 = 0;
//for (; i + k <= n; i += k) ans1 = (ans1 + k)%MOD*2%MOD;
ans1 = (1ll*k*(power(2,(n - i)/k + 1) - 2 + MOD))%MOD;
//printf("%d\n",ans1);
(ans1 += MOD)%=MOD;
i = (n -i)/k * k + i;
(ans1 += n - i)%=MOD;
printf("%d\n",(ans + ans1)%MOD);
}
B - Book of Evil
一开始看错题目了……其实这题很水……只要求出每个点离它自己最远的damaged的点,最后再一个一个点枚举过去,判断过去即可。
#include <cstdio>
#include <algorithm>
#include <cstring>
const int N = 100000 + 9;
int n,m,p[N],d,son[N],ec,fa[N];
struct Edge{int link,next;}es[N*2];
struct node{int dis,v;}f[N],g[N];
inline void addedge(const int x,const int y)
{
es[++ec].link = y;
es[ec].next = son[x];
son[x] = ec;
}
inline void Addedge(const int x,const int y)
{addedge(x,y);addedge(y,x);}
inline void update(const int u,node x)
{
if (x.dis == -1) return;
++x.dis;
if (f[u].dis < x.dis) g[u] = f[u],f[u] = x;
else if (g[u].dis < x.dis) g[u] = x;
}
void dfs(const int root)
{
static int son1[N];
memcpy(son1,son,sizeof son);
for (int u = root; u;) {
if (son[u]) {
const int v = es[son[u]].link;
son[u] = es[son[u]].next;
if (v == fa[u]) continue;
fa[v] = u;
u = v;
continue;
}
update(fa[u],f[u]);
u = fa[u];
}
for (int u = root; u;) {
if (son1[u]) {
const int v = es[son1[u]].link;
son1[u] = es[son1[u]].next;
if (v == fa[u]) continue;
fa[v] = u;
if (f[u].v == f[v].v) update(v,g[u]);
else update(v,f[u]);
u = v;
continue;
}
u = fa[u];
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
#endif
scanf("%d%d%d",&n,&m,&d);
memset(f, -1, sizeof f);
memset(g, -1, sizeof g);
for (int i = 1,x; i <= m; ++i) {
scanf("%d",&x);
f[x].dis = 0;
f[x].v = x;
}
for (int i = 1,x,y; i < n; ++i) {
scanf("%d%d",&x,&y);
Addedge(x,y);
}
dfs(1);
int ans = 0;
for (int i = 1; i <= n; ++i) if (f[i].dis <= d) ++ans;
printf("%d\n",ans);
}
C - Divisor Tree
这题有点意思。观察后不难得出除了root和leave以外的点都是所给的数,而root也有可能是。关键是接下来怎么弄……方法应该有很多。不过我想不出好的方法……
于是去OrzTutorial。其实这个做法挺暴力的……是O(N!)。由于每个所给的数的father也是所给的数或root,并且比它本身来得大。于是我们可以给a[i]排序,然后枚举树的形态。注意细节处理。
#include <cstdio>
#include <algorithm>
const int N = 9;
int ans = 0x7fffffff,n,pnum[N],cnt;
long long a[N],root;
inline void getpnum()
{
for (int i = 1; i <= n; ++i) {
long long x = a[i];
for (long long j = 2; j*j <= x; ++j)
for (;x % j == 0;x /= j) ++pnum[i];
if (x != 1) ++pnum[i];
}
}
void dfs2(const int idx,const int sum)
{
if (idx == 0) {ans = std::min(ans,sum + n + 1);return;}
for (int i = n; i > idx; --i) {
if (a[i] % a[idx] == 0) {
a[i] /= a[idx];
dfs2(idx - 1,sum);
a[i] *= a[idx];
}
}
dfs2(idx - 1,sum + pnum[idx]);
}
bool dfs1(const int idx)
{
if (idx == 0) {ans = pnum[n] + n;return 1;}
for (int i = n; i > idx; --i) {
if (a[i] % a[idx] == 0) {
a[i] /= a[idx];
if (dfs1(idx - 1)) {
a[i] = a[i]*a[idx];
return 1;
}
a[i] = a[i]*a[idx];
}
}
return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
#endif
scanf("%d",&n);
for (int i = 1; i <= n; ++i) scanf("%I64d", a + i);
std::sort(a + 1,a + 1 + n);
root = a[n];
getpnum();
for (int i = 1; i <= n; ++i) if (pnum[i] == 1) ++cnt;
//memcpy(back,a,sizeof a);
if (!dfs1(n - 1))
dfs2(n,0);
printf("%d\n",ans - cnt);
}
D - GCD Table
这题有点坑……一开始想复杂了。其实:
gcd(i,j) = a[idx] ===> a[idx] | i a[idx] | j
就是这样,仅此而已。
然后可以证明row = lcm(a[1], a[2], a[3], ... ,a[n])
证明也很简单。
首先lcm * x (x > 0)肯定可以。只需考虑gcd(lcm,j) != gcd(lcm * x,j)的情况。
令gcd(lcm * x,j) = d。则d | j, d 不整除 lcm。
若这个位置是合法的话,则有a[i] = d 不整除 lcm。这明显是矛盾的。
对于col:
col = - k + 1 (mod a[k])
然后解线性同余方程组,对答案check即可。
Postscript: 注意乘法的地方,会爆long long。所以用类似快速幂的方法处理。
附图一张(描述了大家被这个trick坑的惨状……)
//greater than max_long_long ... so use quick_multiply (qmult)!
#include <cstdio>
#include <cmath>
const int N = 10000 + 9;
typedef long long ll;
ll n,m,a[N],K;
struct Triple
{
ll x,y,z;
Triple(const ll _x,const ll _y,const ll _z):
x(_x),y(_y),z(_z){}
};
Triple exgcd(const ll a,const ll b)
{
// Ax1 + By1 = ax + by
// A = b, B = a % b
// b * x1 + (a - a/b*b) * y1 = a * x + b * y
// a*y1 + b*(x1 - a/b*y1) = a*x + b*y
// x = y1, y = x1 - a/b*y1
if (!b) return Triple(1,0,a);
Triple last(exgcd(b,a%b));
return Triple(last.y,last.x - a/b * last.y,last.z);
}
ll gcd(ll a,ll b)
{
for (ll t;b;)
t = a,a = b,b = t % b;
return a;
}
bool calc_row()
{
ll last = 1;
for (int i = 1; i <= K; ++i) {
ll tmp = gcd(last,a[i]);
if (last / tmp > n / a[i]) return false;
last = last / tmp * a[i];
}
return true;
}
ll qmult(ll x,ll k,const ll mod)
{
ll res = 0,t = 1;
if (k < 0) t = -1,k = -k;
for (;k;k >>= 1,x = x*2%mod)
if (k&1) res = (res + x) % mod;
return res*t;
}
bool calc_col()
{
// j = -k (mod a[k + 1])
// x = k1 (mod a1) <=> x = a1*p1 + k1
// x = k2 (mod a2) <=> x = a2*p2 + k2
// x = a1*p1 + k1 = a2*p2 + k2 <=> a1*p1 - a2*p2 = k2 - k1
// x = a1*p1 + k1 (mod lcm(a1,a2))
ll lastk = 0,lasta = a[1];
if (lasta + K - 1 > m) return false;
for (int i = 2; i <= K; ++i) {
ll k = (a[i] - i + 1) % a[i];
Triple s(exgcd(lasta, a[i]));
if ((k - lastk) % s.z) return false;
const ll mod = a[i] / s.z;
const ll times = (k - lastk) / s.z % mod;
s.x %= mod;
if (fabs((double)s.x * (double)times) > 1e15) s.x = (qmult(s.x,times,mod) + mod)%mod;
else s.x = (s.x % mod * times % mod + mod) % mod;
lastk += lasta * s.x;
lasta = lasta / s.z * a[i];
if ((lastk ? lastk : lasta) + K - 1 > m) return false;
}
lastk = lastk ? lastk : lasta;
for (int i = 1; i <= K; ++i)
if (gcd(lasta,lastk + i -1) != a[i]) return false;
return true;
}
void solve()
{
if (!calc_row() || !calc_col()) puts("NO");
else puts("YES");
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("D.in","r",stdin);
freopen("D.out","w",stdout);
#endif
scanf("%I64d%I64d%I64d",&n,&m,&K);
for (int i = 1; i <= K; ++i) scanf("%I64d",a + i);
solve();
}
E - Optimize!
这题就比较简单了,方法有挺多的吧……我一开始想了个傻叉办法(SPlay……),麻烦得半死……
先sort b[] (从小到大)
令x[i] = min{j | s[i] + b[j] >= h} , y[i] = (x[idx] = i 的个数) , sum[i] = y[i] + y[i + 1] + ... + y[len]
用各种数据结构维护之,然后如果min(len - i + 1 - sum[i]) >= 0 就给ans 加 1。
P.S. 注意细节处理。
#include <cstdio>
#include <algorithm>
const int N = 150000 + 9;
int a[N],min[N*4],tag[N*4],b[N],n,len,h,L,R,D;
inline void push_up(const int idx)
{min[idx] = std::min(min[idx * 2], min[idx * 2 + 1]);}
inline void push_down(const int idx)
{
if (!tag[idx]) return;
tag[idx * 2] += tag[idx]; tag[idx * 2 + 1] += tag[idx];
min[idx * 2] += tag[idx]; min[idx * 2 + 1] += tag[idx];
tag[idx] = 0;
}
void modify(const int idx,const int l,const int r)
{
if (L <= l && r <= R) return (void)(min[idx] += D,tag[idx] += D);
const int mid = (l + r) / 2;
if (tag[idx]) push_down(idx);
if (L <= mid) modify(idx * 2, l, mid);
if (mid < R) modify(idx * 2 + 1, mid + 1, r);
push_up(idx);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("E.in","r",stdin);
freopen("E.out","w",stdout);
#endif
scanf("%d%d%d",&n,&len,&h);
for (int i = 1; i <= len; ++i) {
scanf("%d",b + i);
L = R = i;
D = len - i + 1;
modify(1,1,len);
}
for (int i = 1; i <= n; ++i) {scanf("%d",a + i); a[i] = h - a[i];}
std::sort(b + 1, b + 1 + len);
int cnt = 0,ans = 0;
for (int i = 1; i <= len; ++i) {
if (a[i] > b[len]) {++cnt;continue;}
if (i != 1 && a[i] <= 0) continue;
L = 1; R = std::lower_bound(b + 1, b + 1 + len,a[i]) - b; D = -1;
modify(1,1,len);
}
if (!cnt && min[1] >= 0) ++ans;
for (int i = len + 1; i <= n; ++i) {
if (a[i - len] <= b[len]) {
L = 1; R = std::lower_bound(b + 1, b + 1 + len,a[i - len]) - b; D = 1;
modify(1,1,len);
}else --cnt; if (a[i - len + 1] <= 0) {
L = 1; R = std::lower_bound(b + 1, b + 1 + len,a[i - len + 1]) - b; D = -1;
modify(1,1,len);
} if (a[i] > b[len]) {++cnt;continue;}
if (a[i] > 0) {
L = 1; R = std::lower_bound(b + 1, b + 1 + len,a[i]) - b; D = -1;
modify(1,1,len);
} if (!cnt && min[1] >= 0) ++ans;
}
printf("%d\n",ans);
}
Codeforces Round #196 (Div. 1) 题解的更多相关文章
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- Codeforces Round #608 (Div. 2) 题解
目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...
- Codeforces Round #525 (Div. 2)题解
Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...
- Codeforces Round #528 (Div. 2)题解
Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...
- Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F
Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- Codeforces Round #665 (Div. 2) 题解
Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
- Codeforces Round #383 (Div. 2) 题解【ABCDE】
Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...
随机推荐
- 面试精选之Promise
常见Promise面试题 我们看一些 Promise 的常见面试问法,由浅至深. 1.了解 Promise 吗? 2.Promise 解决的痛点是什么? 3.Promise 解决的痛点还有其他方法可以 ...
- 阅读关于DuReader:百度大规模的中文机器阅读理解数据集
很久之前就得到了百度机器阅读理解关于数据集的这篇文章,今天才进行总结!.... 论文地址:https://arxiv.org/abs/1711.05073 自然语言处理是人工智能皇冠上的明珠,而机器阅 ...
- Android控件——Button与ImageButton
1.简单介绍
- perl HTML::LinkExtor模块(1)
use LWP::Simple; use HTML::LinkExtor; $html = get("http://www.baidu.com"); $link = HTML::L ...
- 【Android XML】Android XML 转 Java Code 系列之 Selector(2)
今天我们要把drawable下的selector的XML文件转换成Java代码.(打包进jar,不依赖apk) 在转换工具中的代码为: https://github.com/SickWorm/Andr ...
- 在Perl中采用open进行管道操作
在Perl中采用open进行管道操作 http://blog.sina.com.cn/s/blog_4840fe2a0100b8na.html perl exec管道和子进程 http://blog. ...
- Tensorflow项目实战一:MNIST手写数字识别
此模型中,输入是28*28*1的图片,经过两个卷积层(卷积+池化)层之后,尺寸变为7*7*64,将最后一个卷积层展成一个以为向量,然后接两个全连接层,第一个全连接层加一个dropout,最后一个全连接 ...
- node.js3
第一部分:express(MVC) 1.下载express npm install express --save 2.引入express require('express') 中间件 body-par ...
- 将MongoDB安装成为Windows服务
使用以下命令将MongoDB安装成为Windows服务.笔者的MongoDB目录为D:\Program Files\mongodb 切换到D:\Program Files\mongodb\bin> ...
- leetcode 之Single Number(14)
这题并不难,但需要注意细节. ListNode* addTwo(ListNode *l1, ListNode *l2) { ListNode dummy(-); ; ListNode *prev = ...