@Dmaxiya
2018-08-17T10:26:23.000000Z
字数 7824
阅读 933
Codeforces
Contests 链接:Codeforces Round #489 (Div. 2)
过题数:3
排名:289/6253
有一个长度为 的序列,每一秒她可以将这个序列上的所有非零的数字加上同一个数字,如果这个序列所有的数字都等于 ,那么这个序列就爆炸了,问最少需要多少秒,能够使这个序列爆炸。
第一行包含一个整数 ,第二行包含 个整数 表示这个序列中的每一个数字。
一个整数,表示最少能够使这个序列爆炸的时间。
输入 | 输出 |
---|---|
5 1 1 1 1 1 |
1 |
3 2 0 -1 |
2 |
4 5 -6 -5 1 |
4 |
直接判断序列中有多少个不同的非零数字。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
typedef long long LL;
int n, x;
set<int> st;
int main() {
#ifdef Dmaxiya
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // Dmaxiya
ios::sync_with_stdio(false);
while(scanf("%d", &n) != EOF) {
st.clear();
for(int i = 0; i < n; ++i) {
scanf("%d", &x);
if(x != 0) {
st.insert(x);
}
}
int ans = st.size();
printf("%d\n", ans);
}
return 0;
}
定义一对好的整数,这对整数必须满足 且 ,问在区间 内,有多少对好的整数。如果 ,则 与 被认为是不同的整数对。
输入包含四个整数 。
输出问题的答案。
输入 | 输出 |
---|---|
1 2 1 2 | 2 |
1 12 1 12 | 4 |
50 100 3 30 | 0 |
要满足 且 ,首先必须满足 ,否则不存在满足要求的整数对。设 ,则 且 ,所以 ,因此问题就转化为求在区间 内的 的因子对 的个数,其中 , 地枚举即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
typedef long long LL;
int l, r, x, y, ans;
int gcd(int a, int b) {
return b == 0? a: gcd(b, a % b);
}
int main() {
#ifdef Dmaxiya
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // Dmaxiya
ios::sync_with_stdio(false);
while(scanf("%d%d%d%d", &l, &r, &x, &y) != EOF) {
ans = 0;
if(y % x != 0) {
printf("0\n");
continue;
}
y /= x;
l = (l + x - 1) / x;
r /= x;
for(int i = 1; i <= y / i; ++i) {
if(y % i == 0) {
int ii = y / i;
if(i >= l && i <= r && ii >= l && ii <= r && gcd(i, ii) == 1) {
++ans;
if(i != ii) {
++ans;
}
}
}
}
printf("%d\n", ans);
}
return 0;
}
最初一个衣柜中有 条裙子,每个月月末,衣柜里的裙子数就会翻倍,并且除了最后一个月以外,其他月的月末如果衣柜里有裙子的话都会有 的概率被偷一条裙子,问 个月后,衣柜里裙子数量的期望值。由于这个期望值总是整数,所以可以将答案对 取模后输出。
两个整数 。
输出对 取模后的答案。
输入 | 输出 |
---|---|
2 0 | 4 |
2 1 | 7 |
3 2 | 21 |
先打出 时的表:
月份 0 1 2 3 4 翻倍 期望 被偷 可以发现,答案就是 ,由于 很大,所有要用个快速幂。最后要注意一下 的情况,由于对 翻倍仍然是 ,这时候没有裙子可以被偷,所以不满足上面的规律,应直接输出 。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
typedef long long LL;
const LL MOD = 1000000000 + 7;
LL x, k;
LL fast_pow(LL res, LL n) {
LL ans = 1;
for(ans = 1; n != 0; n >>= 1) {
if(n % 2 == 1) {
ans = (ans * res) % MOD;
}
res = (res * res) % MOD;
}
return ans;
}
int main() {
#ifdef Dmaxiya
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // Dmaxiya
ios::sync_with_stdio(false);
while(scanf("%I64d%I64d", &x, &k) != EOF) {
if(x == 0) {
printf("0\n");
continue;
}
x %= MOD;
LL ans = fast_pow(2, k + 1);
ans = (ans * x) % MOD;
LL tmp = fast_pow(2, k);
tmp = ((tmp - 1) % MOD + MOD) % MOD;
ans -= tmp;
ans = (ans % MOD + MOD) % MOD;
printf("%I64d\n", ans);
}
return 0;
}
给一个长度为 的序列,要求找到满足 的子段个数,其中 为被选中子段的数字乘积, 为被选中子段的数字和。
第一行包含两个整数 和 。第二行为 个整数 。
输出满足条件的子段数量。
输入 | 输出 |
---|---|
1 1 1 |
1 |
4 2 6 3 8 1 |
2 |
由于 的最大值为 ,所以满足条件的子段内,不等于 的数字个数不会超过 个 ,因此只要关注不等于 的数字即可,通过枚举起点,当 时跳出枚举终点的循环,时间复杂度可以达到 。
我们可以知道,当 时,答案可以 ;当 时,需要一个非 的数字加入这个子段,才能使 增大,而更多的 反而使得 增大,不利于寻找答案,所以这时候应直接跳到下一个非 的位置;当 时,更多的 将会使 增大,这时候可以直接计算出所需要的 的数量:,解得 ,如果后面有连续的 个 ,则可以直接跳到这个位置,否则直接跳到下一个非 数字。最后注意一下乘法容易爆 ,应该用除法做比较。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
typedef long long LL;
const int maxn = 200000 + 100;
int n, Index;
LL ans;
LL k, sum, num[maxn];
int Next[maxn];
int main() {
#ifdef Dmaxiya
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // Dmaxiya
ios::sync_with_stdio(false);
while(scanf("%d%I64d", &n, &k) != EOF) {
sum = 0;
ans = 0;
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &num[i]);
sum += num[i];
}
Index = n + 1;
for(int i = n; i > 0; --i) {
Next[i] = Index;
if(num[i] != 1) {
Index = i;
}
}
for(int i = 1; i <= n; ++i) {
LL p, s;
p = 1;
s = 0;
for(int j = i; j <= n; ++j) {
if(!(p <= sum * k / num[j])) {
break;
}
p *= num[j];
s += num[j];
if(p == s * k) {
++ans;
continue;
}
int jj = Next[j] - 1;
if(p < s * k) {
if(jj != j) {
s += jj - j;
j = jj;
}
continue;
}
LL x = (p - k * s + k - 1) / k;
if(j + x > jj) {
x = jj - j;
}
s += x;
j += x;
if(p == k * s) {
++ans;
}
}
}
printf("%I64d\n", ans);
}
return 0;
}
给定一个长度为 的序列 ,记 ,有 次操作,每次操作将 改为 ,问每次操作之后,哪个位置上的数字满足 。
第一行为两个整数 ,第二行为 个整数 ,接下去有 行,每行两个整数 ,表示执行操作 。
输出 行,第 行表示进行第 次操作之后,满足 的 ,如果有多个解,则输出任意一个,如果不存在解,则输出 。
输入 | 输出 |
---|---|
2 1 1 3 1 2 |
-1 |
3 4 2 2 3 1 1 1 2 2 4 3 6 |
3 2 -1 3 |
10 7 0 3 1 4 6 2 7 8 10 1 2 5 1 3 9 36 4 10 4 9 1 2 1 0 |
1 -1 9 -1 4 -1 1 |
我们定义一个新的数组 ,于是相当于要在 数组中查找满足条件 的位置,对于这个数组,如果进行操作 ,对于第 个数字,相当于 ,而这个数字的改变,也会使得在位置 之后的前缀和发生改变,相当于 ,而对于 数组,相当于执行了
这种修改正是区间加减,于是可以用线段树对这种修改进行维护,要找到 数组中为 的数组,我们可以维护区间最大值,因为对于 这样一个数组,其中大于 的数字个数是很少的,假设 数组中每个数字都大于 ,在最坏情况下( 数组长度最长), 数组中的元素应该为 , 最大为 ,因此 数组中最多只有 个数字大于 ,通过维护区间最大值的方法找 ,每次查找时间复杂度为 ,而查找出错(找到比 大的数字)的次数最大为 ,因此总的时间复杂度为 。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
typedef long long LL;
const int maxn = 200000 + 100;
int n, q, p;
LL x;
LL num[maxn], sum[maxn];
LL Max[maxn << 2], lazy[maxn << 2];
void push_up(int rt) {
Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}
void push_down(int rt) {
if(lazy[rt] != 0) {
Max[rt << 1] += lazy[rt];
Max[rt << 1 | 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
lazy[rt << 1] += lazy[rt];
lazy[rt] = 0;
}
}
void build(int l, int r, int rt) {
lazy[rt] = 0;
if(l == r) {
Max[rt] = num[l] - sum[l - 1];
return ;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
push_up(rt);
}
void update(int L, int R, LL x, int l, int r, int rt) {
if(L <= l && r <= R) {
lazy[rt] += x;
Max[rt] += x;
return ;
}
push_down(rt);
int m = (l + r) >> 1;
if(L <= m) {
update(L, R, x, l, m, rt << 1);
}
if(m < R) {
update(L, R, x, m + 1, r, rt << 1 | 1);
}
push_up(rt);
}
int query(int l, int r, int rt) {
if(l == r) {
if(Max[rt] == 0) {
return l;
}
return -1;
}
push_down(rt);
int m = (l + r) >> 1;
int ret = -1;
if(Max[rt << 1] >= 0) {
ret = max(ret, query(l, m, rt << 1));
}
if(ret != -1) {
return ret;
}
if(Max[rt << 1 | 1] >= 0) {
ret = max(ret, query(m + 1, r, rt << 1 | 1));
}
return ret;
}
int main() {
#ifdef Dmaxiya
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // Dmaxiya
ios::sync_with_stdio(false);
while(scanf("%d%d", &n, &q) != EOF) {
sum[0] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &num[i]);
sum[i] = sum[i - 1] + num[i];
}
build(1, n, 1);
while(q--) {
scanf("%d%I64d", &p, &x);
LL d = x - num[p];
num[p] = x;
update(p, p, d, 1, n, 1);
if(p != n) {
update(p + 1, n, -d, 1, n, 1);
}
printf("%d\n", query(1, n, 1));
}
}
return 0;
}