Codeforces GoodBye 2015

本文详细解析了Codeforces GoodBye2015竞赛中的三个问题,包括如何解决通过数、一周内特定日期的天数、二进制表示中特定条件的数的数量以及矩阵中骨牌放置的合法方式计数。涵盖了多种算法和数据结构应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Codeforces GoodBye 2015

通过数:3
Standing: 1231/7482
A:
返回2016年星期几有几天,或者返回一个月的第几日有几天。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
char op[100];
int solve_week(int a)
{
    if(a == 5 || a == 6)    return 53;
    return 52;
}
int solve_month(int a)
{
    if(a <= 29) return 12;
    if(a == 30) return 11;
    else return 7;
}
int main()
{
    int n;
    while(scanf("%d", &n) != EOF){
        scanf("%s", op);
        scanf("%s", op);
        int ans;
        if(op[0] == 'w')    ans = solve_week(n);
        else    ans = solve_month(n);
        printf("%d\n", ans);
    }
    return 0;
}

B:
问[a,b]区间中,满足二进制表示上只有一位为0、其余位为1的数有多少个。
满足区间减法,所以直接solve(b) - solve(a-1)即可。
Solve(a)是查找最大的小于等于a的满足要求的数,然后数它后面有几个数。
还有一种做法是先枚举出所有的满足要求的数,然后找到最大的满足的数。大同小异。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int MAXN = 100;
int solve(LL a)
{
    LL temp = a;
//    while(temp){
//        if(temp & 1)    printf("1");
//        else    printf("0");
//        temp >>= 1;
//    }
    if(a <= 0)  return 0;
    int ans = 0;
    for(int i = 0 ; ; i++){
        LL two = (LL)1 << i;
        two -= 1;
        if(two < a) continue;
        for(int j = 0 ; j <= i - 2 ; j++){
            if( (two ^ ((LL)1 << j)) <= a){
                ans = i - 2 - j + 1;
                ans += (i - 1) * (i - 2) / 2;
//                printf("two ^ (LL)1 << j = %I64d\n", two ^ ((LL)1 << j) );
//                printf("two = %I64d, i = %d, j = %d, ans = %d\n", two, i, j, ans);
                return ans;
            }
        }
        return (i - 1) * (i - 2) / 2;
    }
}
int main()
{
    LL a, b;
    while(scanf("%I64d%I64d", &a, &b) != EOF){
        if(a > b)   swap(a, b);
        printf("%d\n", solve(b) - solve(a - 1));
    }
    return 0;
}

C:
一个矩阵(500*500),有些障碍点和空格点。
现在可以放一种1*2的骨牌,骨牌只能放在空格点。
问对于(x1,y1,x2,y2)这个矩阵,有多少种合法的放骨牌的方式。

很明显的dp[x2][y2] + dp[x1][y1] - dp[x2][y1] - dp[x1][y2]的模式,因为骨牌横竖放置的不一样所以稍微调一下下标就可以。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int MAXN = 500 + 5;
LL cntx[MAXN][MAXN], cnty[MAXN][MAXN];
LL cnt[MAXN][MAXN];
char g[MAXN][MAXN];
int n, m;
void init()
{
    for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j++){
            cntx[i][j] = cntx[i][j - 1];
            if(j > 1 && g[i][j - 1] == '.' && g[i][j] == '.')   cntx[i][j]++;
        }
    }
    for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j++){
            cnty[i][j] = cnty[i - 1][j];
            if(i > 1 && g[i][j] == '.' && g[i - 1][j] == '.')   cnty[i][j]++;
        }
    }
//    printf("///***cntx\n");
//    for(int i = 1 ; i <= n ; i++){
//        for(int j = 1 ; j <= m ; j++)   printf("%d ", cntx[i][j]);
//        printf("\n");
//    }
//    printf("***///\n");
//    printf("///***cnty\n");
//    for(int i = 1 ; i <= n ; i++){
//        for(int j = 1 ; j <= m ; j++)   printf("%d ", cnty[i][j]);
//        printf("\n");
//    }
//    printf("***///\n");
    for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j++)   cntx[i][j] += cntx[i - 1][j];
    }
    for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= m ; j++)   cnty[i][j] += cnty[i][j - 1];
    }
//    printf("\n\nafter\n");
//    printf("///***cntx\n");
//    for(int i = 1 ; i <= n ; i++){
//        for(int j = 1 ; j <= m ; j++)   printf("%d ", cntx[i][j]);
//        printf("\n");
//    }
//    printf("***///\n");
//    printf("///***cnty\n");
//    for(int i = 1 ; i <= n ; i++){
//        for(int j = 1 ; j <= m ; j++)   printf("%d ", cnty[i][j]);
//        printf("\n");
//    }
//    printf("***///\n");

//    for(int i = 1 ; i <= n ; i++)   for(int j = 1 ; j <= m ; j++)   cnt[i][j] = cntx[i][j] + cnty[i][j];
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF){
        memset(cntx, 0, sizeof(cntx));
        memset(cnty, 0, sizeof(cnty));
        memset(cnt, 0, sizeof(cnt));
        for(int i = 1 ; i <= n ; i++){
            scanf("%s", g[i] + 1);
        }
        init();
        int q;
        scanf("%d", &q);
        while(q--){
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            LL ans1 = cntx[x2][y2] + cntx[x1 - 1][y1] - cntx[x2][y1] - cntx[x1 - 1][y2];
            LL ans2 = cnty[x2][y2] + cnty[x1][y1 - 1] - cnty[x2][y1 - 1] - cnty[x1][y2];
            LL ans = ans1 + ans2;
//            LL ans2 =
            printf("%I64d\n", ans);
        }
    }
    return 0;
}

D:
http://blog.youkuaiyun.com/beihai2013/article/details/50448171
E:
http://blog.youkuaiyun.com/beihai2013/article/details/50448175
F:
http://blog.youkuaiyun.com/beihai2013/article/details/50448178

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值