CodeForces - 895

42 篇文章 0 订阅
30 篇文章 0 订阅

CodeForces - 895A Pizza Separation

Students Vasya and Petya are studying at the BSU (Byteland State University). At one of the breaks they decided to order a pizza. In this problem pizza is a circle of some radius. The pizza was delivered already cut into n pieces. The i-th piece is a sector of angle equal to ai. Vasya and Petya want to divide all pieces of pizza into two continuous sectors in such way that the difference between angles of these sectors is minimal. Sector angle is sum of angles of all pieces in it. Pay attention, that one of sectors can be empty.
Input
The first line contains one integer n (1 ≤ n ≤ 360) — the number of pieces into which the delivered pizza was cut.
The second line contains n integers ai (1 ≤ ai ≤ 360) — the angles of the sectors into which the pizza was cut. The sum of all ai is 360.
Output
Print one integer — the minimal difference between angles of sectors that will go to Vasya and Petya.

Example
Input
4
90 90 90 90
Output
0
Input
3
100 100 160
Output
40
Input
1
360
Output
360
Input
4
170 30 150 10
Output
0
Note
In first sample Vasya can take 1 and 2 pieces, Petya can take 3 and 4 pieces. Then the answer is |(90 + 90) - (90 + 90)| = 0.

In third sample there is only one piece of pizza that can be taken by only one from Vasya and Petya. So the answer is |360 - 0| = 360.
In fourth sample Vasya can take 1 and 4 pieces, then Petya will take 2 and 3 pieces. So the answer is |(170 + 10) - (30 + 150)| = 0.
Both red and green sectors consist of two adjacent pieces of pizza. So Vasya can take green sector, then Petya will take red sector.

题意:
一个圆形蛋糕,按角度被分成n份,分配给两个人吃(分配时只能分配连续的蛋糕块),使两个人分到蛋糕的差最小。
思路:
(刚开始没读清题,以为不连续也行,就用背包去写了,关键巧妙地过了样例)尺取求最接近180度的分法即可,ans = min(ans, abs(180 - sum) * 2);

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;

const int MAXN = 400;
int dp[MAXN][MAXN], a[MAXN];

int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int L = 0, R = 0, sum = 0, ans = 1000;
    for(int i = 1; i <= n; i++) {
        sum += a[i];
        if(sum > 180) {
            while(sum > 180) {
                ans = min(ans, abs(180 - sum) * 2);
                sum -= a[++L];
            }
        }
        ans = min(ans, abs(180 - sum) * 2);
    }
    printf("%d\n", ans);
    return 0;
}

CodeForces - 895B XK Segments

While Vasya finished eating his piece of pizza, the lesson has already started. For being late for the lesson, the teacher suggested Vasya to solve one interesting problem. Vasya has an array a and integer x. He should find the number of different ordered pairs of indexes (i, j) such that ai ≤ aj and there are exactly k integers y such that ai ≤ y ≤ aj and y is divisible by x.
In this problem it is meant that pair (i, j) is equal to (j, i) only if i is equal to j. For example pair (1, 2) is not the same as (2, 1).
Input
The first line contains 3 integers n, x, k (1 ≤ n ≤ 105, 1 ≤ x ≤ 109, 0 ≤ k ≤ 109), where n is the size of the array a and x and k are numbers from the statement.
The second line contains n integers ai (1 ≤ ai ≤ 109) — the elements of the array a.
Output
Print one integer — the answer to the problem.
Example
Input
4 2 1
1 3 5 7
Output
3
Input
4 2 0
5 3 1 7
Output
4
Input
5 3 1
3 3 3 3 3
Output
25
Note
In first sample there are only three suitable pairs of indexes — (1, 2), (2, 3), (3, 4).
In second sample there are four suitable pairs of indexes(1, 1), (2, 2), (3, 3), (4, 4).
In third sample every pair (i, j) is suitable, so the answer is 5 * 5 = 25.

题意:
第一行n,x,k,下面n个数,求[ a[i], a[j] ]区间恰好包含k个x的倍数,求这种区间的个数。
思路:
sort+二分,二分恰好满足条件的最小值和最大值下标。卡的点比较多,需要讨论几种情况。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;

const LL MAXN = 1e5 + 5;
LL a[MAXN];

int main() {
    LL k, x, n;
    scanf("%lld %lld %lld", &n, &x, &k);
    for(LL i = 0; i < n; i++)
        scanf("%lld", &a[i]);
    sort(a, a + n);
    LL sum = 0;
    for(LL i = 0; i < n; i++) {
        LL ans1 = (a[i] / x + k) * x;
        if(a[i] % x == 0) ans1 -= x;
        LL ans2 = ans1 + x - 1; 
        ans1 = max(ans1, a[i]);
        LL cnt1 = lower_bound(a, a + n, ans1) - a;
        LL cnt2 = upper_bound(a, a + n, ans2) - a;
        sum += cnt2 - cnt1;
    }
    printf("%lld\n", sum);
    return 0;
}

CodeForces - 895C Square Subsets

Petya was late for the lesson too. The teacher gave him an additional task. For some array a Petya should find the number of different ways to select non-empty subset of elements from it in such a way that their product is equal to a square of some integer.
Two ways are considered different if sets of indexes of elements chosen by these ways are different.
Since the answer can be very large, you should find the answer modulo 109 + 7.
Input
First line contains one integer n (1 ≤ n ≤ 105) — the number of elements in the array.
Second line contains n integers ai (1 ≤ ai ≤ 70) — the elements of the array.
Output
Print one integer — the number of different ways to choose some elements so that their product is a square of a certain integer modulo 109 + 7.
Example
Input
4
1 1 1 1
Output
15
Input
4
2 2 2 2
Output
7
Input
5
1 2 4 5 8
Output
7
Note
In first sample product of elements chosen by any way is 1 and 1 = 12. So the answer is 24 - 1 = 15.
In second sample there are six different ways to choose elements so that their product is 4, and only one way so that their product is 16. So the answer is 6 + 1 = 7.

题意:
n个数,选任意个数字相乘,结果是一个数的平方根,求这样的组合个数。
思路:
看到数值最大是70,解题点肯定在这,只想到分解质因子,找出现偶数次的组合,没学过状压不知道具体怎么处理了。
状压:一个数含有这个质因子奇数个,那么他状态的这一位是1,一个数含有这个这个质因子偶数个,那么状态的这一位是0。
按照这个思路,找能够组合成平方根的数,有ans个组合,那么结果就是pow(2,ans)-1;
分析:处理成二进制形式,来表示一些操作(类似的有容斥的二进制写法);

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;

const int mod = 1e9 + 7;
const int MAXN = 1e5 + 5;
int a[MAXN], prim[110], dp[MAXN];
int p = 0;

void init() {
    for(int i = 2; i <= 70; i++) {
        bool flag = true;
        for(int j = 2; j <= sqrt(i); j++) {
            if(i % j == 0) {
                flag = false;
                break;
            }
        }
        if(flag) prim[p++] = i;
    }
}

int main() {
    int n;
    init();
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    sort(a, a + n);
    int k = 0;
    for(int i = 0; i < n; i++) {
        int ans = 0;
        for(int j = 0; j < p; j++) {
            while(a[i] % prim[j] == 0) {
                a[i] /= prim[j];
                ans ^= (1 << j);
            }
        }
        for(int j = 0; j < k; j++) {
            ans = min(ans, ans ^ dp[j]);
        }
        if(ans) dp[k++] = ans;
    }
    LL sum = 1;
    for(int i = k; i < n; i++) {
        sum *= 2;
        sum %= mod;
    }
    printf("%lld\n", (sum - 1 + mod) % mod);
    return 0;
}

这场的题稍微难度大一点呀,补不动。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值