Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017 - Final Round Div. 2 Edition)

补完继续更……



A.

简单地模拟题,给出月份m和该月第一天的星期数d,问在图中的日历中需要写几列。写一个公式即可。

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>
//#include <iomanip.h>
#include <limits.h>
//#include <strstrea.h>
//#include <fstream.h>
#define ll long long
#define ull unsigned long long
//#define int64 long long
#define INF  0x3f3f3f3f

using namespace std;

const int maxn = 1e4 + 5;
int n, w, d;


int main() {
    scanf("%d%d", &n, &w);
    if (1 == n || n == 3 || n == 5 || n == 7 || n == 8 || n == 10 || n == 12) d = 31;
    else if (n == 2) d = 28;
    else d = 30;
    int ans = 0;
    ans++;
    d -= (7 - w + 1);
    if (d % 7 == 0) ans += (d / 7);
    else ans += (d / 7 + 1);
    printf("%d\n",ans);
    return 0;
}


B.

题目大意:有n张床,一共m个枕头,Frodo睡在第k张床上,每张床上至少有一个枕头,每张床与相邻的床的枕头数只差最大为1,求能分配给Frodo最多几个枕头。

解析:直接二分答案,每次计算当分配给Frodo now 个枕头时所有床上的最少的枕头数,与m比较即可

反思:这个题刚开始思路是对的,但是二分写的不对……改了改二分的姿势就过了……原来一直用的姿势竟然wa了我就很尴尬……

代码:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>
//#include <iomanip.h>
#include <limits.h>
//#include <strstrea.h>
//#include <fstream.h>
#define ll long long
#define ull unsigned long long
//#define int64 long long
#define INF  0x3f3f3f3f

using namespace std;

const int maxn = 1e4 + 5;
ll n, m, k;

bool check(ll now) {
    ll sum = 0;
    if (now >= k) {
        sum = sum + (2 * now - k) * (k - 1) / 2;
    } else {
        sum = sum + now * (now - 1) / 2 + k - now;
    }
    sum += now;
    if (now - n + k >= 1) {
        sum = sum + (2 * now - 1 - n + k) * (n - k) / 2;
    } else {
        sum = sum + now * (now - 1) / 2 + n - k - now + 1;
    }
    //cout << "now=" << now << " k=" << k << " sum=" << sum << endl;
    return sum <= m;
}

int main() {
    scanf("%I64d%I64d%I64d", &n, &m, &k);
    ll l = 1, r = 1e9, mid, mmax;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (check(mid)) {
            mmax = mid;
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    printf("%I64d\n", mmax);
    return 0;
}

C.

题目大意:题目比较难翻译,最初的题意是n根烤串架在n个位置上烤,给出一个排列p,p[i]表示经过1s后将位置i上的烤串放到位置p[i]上继续烤,同时给出一个序列b[i],b[i]==1时表示烤串放到位置i上时要调转方向,求要使每一根烤串都能在这n种位置上每个方向都考一遍最少需要修改排列p和序列b上的几个数。

反思:比赛时通过画图发现对于一个排列p,每个位置上的数都属于一个循环,即在这个循环中最后会回到自己最初的位置,同一个循环中的k个位置是等效的,即它们彼此可以任意交换但不会跳出循环。当一个排列产生1个循环时无需调整,当产生两个循环时就需要调整p[i]和p[j]使得这两个循环变成一个循环,因此可得对于n个循环(n>1)需要调整n个数使得排列符合题意。然后我们再考虑序列b,对于序列b,假设p符合要求后b中有偶数个1,那么对于任意的位置i,循环完一个周期回到最初位置时的方向应该和最初的方向是相同的,也就是无论循环多少次在每个位置上的方向都是不变的,因此需要b中有奇数个1,使得回到最初位置后i的方向发生改变,那么第二个周期结束后就可以遍历每个位置上的所有方向。


代码:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <functional>
//#include <iomanip.h>
#include <limits.h>
//#include <strstrea.h>
//#include <fstream.h>
#define ll long long
#define ull unsigned long long
//#define int64 long long
#define INF  0x3f3f3f3f

using namespace std;

const int maxn = 2e5 + 5;
int n, b[maxn], p[maxn];
bool vis[maxn];

int f() {
    memset(vis, false, sizeof(vis));
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (!vis[i]) {
            vis[i] = true;
            cnt++;
            int t = p[i];
            while (t != i) {
                vis[t] = true;
                t = p[t];
            }
        }
    }
    return cnt;
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
        if (b[i] == 1) cnt++;
    }
    int ans = f();
    if (ans == 1) ans = 0;
    if (cnt % 2 == 0) ans++;
    printf("%d\n", ans);
    return 0;
}

剩下的水平不够比赛时没来得及看……等补完再更好了

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值