BestCoder Round #56 (div.2)

27 篇文章 0 订阅

HDU 5463 Clarke and minecraft

水题。

先统计出每种材料的总数,然后每64个贪心地放。

放完36个格子即用掉一个背包

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<fstream>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<queue>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
/*
正反循环的宏定义
*/
#define ffr(i,x,y) for(int i=(x),_en=(y);i<=_en;i++)
#define rff(i,x,y) for(int i=(x),_en=(y);i>=_en;i--)
#define clr(f,z) memset(f,z,sizeof(f))
using namespace std;
const int maxn=100005,inf=1<<29;
int dir[][2]={ {0,1},{-1,0},{0,-1},{1,0},{-1,1},{-1,-1},{1,-1},{1,1}};//常用方向数组
int n,m,t;//常用全局变量
int a[maxn],b[maxn],dp[maxn],num[maxn],vis[maxn];//常用全局数组
struct node
{
    int x,y;
};//常用结构体
vector<int>G[maxn];//常用邻接表
/*
函数重载,可根据参数类型,自动选择输入
*/
bool sf(int &x) { return scanf("%d",&x)==1;}
bool sf(char *x){return scanf("%s",x)==1;}
bool sf(double &x){return scanf("%lf",&x)==1;}
bool sf(LL &x) { return scanf("%I64d",&x)==1;}
void pf(int x,int op) {
    op?printf("%d\n",x):printf("%d ",x);//op==0打印数字加空格,op==1打印数字加换行
}
void pf(LL x,int op) {
    op?printf("%I64d\n",x):printf("%I64d ",x);//op==0打印数字加空格,op==1打印数字加换行
}
int get_rand(int n)
{
    return (int)((double)rand() / RAND_MAX * n) ;
}
int main()
{
    // freopen("in.txt","r",stdin);
     //freopen("out.txt","w",stdout);
     //srand(time(NULL));
    sf(t);
    while(t--)
    {
        sf(n);
        clr(num,0);//记录每种材料的总数
        ffr(i,1,n)
        {
            int x,y;
            sf(x);sf(y);
            num[x]+=y;
        }
        int s=0;
        ffr(i,1,500)
        if(num[i])
        {
            if(num[i]%64) s+=num[i]/64+1;//每个格子对多能放64个相同材料
            else s+=num[i]/64;
        }
        int ans;
        if(s%36) ans=s/36+1;//每个背包有36个格子
        else ans=s/36;
        pf(ans,1);
    }
    return 0;
}

HDU 5464 Clarke and problem

给n个数,问你选一些数加起来和是p的倍数方案数是多少。

根据经验可知,算和为某个数的方案数可以用0-1背包搞,此题就是这个模型的变形啦。

定义dp[i][j]:前i个数加起来之和模p后等于j的方案数

则dp[0][0]=1:即什么都不取是一种可行的方案。

如果不取第i个数 则有dp[i][j]+=dp[i-1][j] 

如果取第i个数,则有dp[i][j]+=dp[i-1][(j-a[i])%p];

总的来说有,dp[i][j]+=dp[i-1][j]+dp[i-1][(j-a[i])%p];

那么显然dp[n][0]存的就是答案

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<fstream>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<queue>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
/*
正反循环的宏定义
*/
#define ffr(i,x,y) for(int i=(x),_en=(y);i<=_en;i++)
#define rff(i,x,y) for(int i=(x),_en=(y);i>=_en;i--)
#define clr(f,z) memset(f,z,sizeof(f))
using namespace std;
const int maxn=1005,inf=1<<29;
int dir[][2]={ {0,1},{-1,0},{0,-1},{1,0},{-1,1},{-1,-1},{1,-1},{1,1}};//常用方向数组
int n,m,t;//常用全局变量
LL a[maxn],dp[maxn][maxn];
struct node
{
    int x,y;
};//常用结构体
vector<int>G[maxn];//常用邻接表
/*
函数重载,可根据参数类型,自动选择输入
*/
bool sf(int &x) { return scanf("%d",&x)==1;}
bool sf(char *x){return scanf("%s",x)==1;}
bool sf(double &x){return scanf("%lf",&x)==1;}
bool sf(LL &x) { return scanf("%I64d",&x)==1;}
void pf(int x,int op) {
    op?printf("%d\n",x):printf("%d ",x);//op==0打印数字加空格,op==1打印数字加换行
}
void pf(LL x,int op) {
    op?printf("%I64d\n",x):printf("%I64d ",x);//op==0打印数字加空格,op==1打印数字加换行
}
int get_rand(int n)
{
    return (int)((double)rand() / RAND_MAX * n) ;
}
int main()
{
     //freopen("in.txt","r",stdin);
     //freopen("out.txt","w",stdout);
     //srand(time(NULL));
     LL mod=1000000007;
    sf(t);
    while(t--)
    {
        sf(n);sf(m);
        ffr(i,1,n) sf(a[i]);
        clr(dp,0);dp[0][0]=1;
        ffr(i,1,n) ffr(j,0,m-1)
            {   dp[i][j]+=dp[i-1][j];//不取
                dp[i][j]+=dp[i-1][((j-a[i])%m+m)%m];//取
                dp[i][j]%=mod;
            }
        pf(dp[n][0],1);
    }
    return 0;
}


HDU 5465 Clarke and puzzle

首先你要知道Nim博弈的经典结论。

然后就转化成求矩阵异或和问题了。

但是此题又设计修改,那么很容易想到,我们可以用数据结构维护异或和。用二维线段树和二维树状数组都行吧。

用二维树状数组比较方便,写起来代码很优美~

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int maxn = 510;

typedef long long LL;

int T;
int n,m,q,k,a[maxn][maxn];
LL c[maxn][maxn];

void ins(int x,int y,int k) {
    for (int i = x;i <= n;i +=i&-i) {
        for (int j = y;j <= m;j +=j&-j) {
            c[i][j] ^= k;
        }
    }
}

LL ques(int x,int y) {
    if (x <= 0 || y <= 0) return 0;
    LL ans = 0;
    for (int i = x;i;i -=i&-i) {
        for (int j = y;j;j -=j&-j) {
            ans ^= c[i][j];
        }
    }
    return ans;
}



int main() {
    scanf("%d",&T);
    for (int kase = 1;kase <= T; kase++) {
    memset(c,0,sizeof(c));
    scanf("%d%d%d",&n,&m,&q);
    for (int i = 1;i <= n; i++)
        for (int j = 1;j <= m; j++) {
            scanf("%d",&a[i][j]);
            ins(i,j,a[i][j]);
        }
    for (int i = 1;i <= q; i++) {
        int opt;
        scanf("%d",&opt);
        if (opt == 1) {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            LL ans = ques(x2,y2)^ques(x1-1,y2)^ques(x2,y1-1)^ques(x1-1,y1-1);
            if (ans)
            printf("Yes\n");
            else printf("No\n");
        } else {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            ins(x,y,a[x][y]); ins(x,y,z);
            a[x][y] = z;
        }
    }
    }
    return 0;
}

第四题太变态,搞不来

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值