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;
}
第四题太变态,搞不来