BestCoder Round #56 (div.2)
2015-09-19 23:31
375 查看
HDU 5463 Clarke and minecraft
水题。
先统计出每种材料的总数,然后每64个贪心地放。
放完36个格子即用掉一个背包
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
[0]存的就是答案
HDU 5465 Clarke and puzzle
首先你要知道Nim博弈的经典结论。
然后就转化成求矩阵异或和问题了。
但是此题又设计修改,那么很容易想到,我们可以用数据结构维护异或和。用二维线段树和二维树状数组都行吧。
用二维树状数组比较方便,写起来代码很优美~
第四题太变态,搞不来
水题。
先统计出每种材料的总数,然后每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
[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 [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; }
第四题太变态,搞不来
相关文章推荐
- 2015沈阳网络赛 1002(HDU 5451 矩阵快速幂 + 矩阵循环群)
- hdu1084代码过程的反省
- 包含min函数的栈
- [Mac] Terminal and Vim theme
- B\S备忘录29——MVC3下的JS、CSS合并
- log4j1.2简介
- 2、Windows C++编程约定
- [LeetCode#254] Factor Combinations
- HDU 5455 Fang Fang(关键就是c的个数)——2015 ACM/ICPC Asia Regional Shenyang Online
- RabbitMQ > Spring AMQP
- 百度地图 根据经纬度获取城市或省的名称
- SEO优化-伪静态-URLRewrite 详解
- DOTNET笔记_Convert_CONST_ReadOnly_Enumerator
- 对git的初步认识
- linux创建线程
- OCPV13.02-638
- 如何学习计算机
- 构建centos 5.2系统源码树
- while(cin)循环的控制判断
- Android ListView监听上滑、下滑、滑到顶部/底部