2014 Multi-University Training Contest 7 题解
2014-08-13 17:08
344 查看
<a target=_blank href="http://acm.hdu.edu.cn/showproblem.php?pid=4939"> </a>http://acm.hdu.edu.cn/showproblem.php?pid=4939
HDU 4939题解
题意:
1.红塔,每单位时间造成x的伤害
2.绿塔,在经过之后每单位时间造成y的伤害
3.蓝塔,在经过之后每走一单位距离需要多花z的时间
题解:
显然,红塔肯定放在最后面。绿塔和蓝塔就进行DP求解。dp[i][j]表示前i个塔有j个塔是绿塔时,造成的最大伤害。同时以剩下的n-i个全为红塔,来求出最大伤害ans。
#include<stdio.h> http://blog.csdn.net/lyhvoyage/article/details/38533545 #include<string.h> #include<math.h> #include<algorithm> #define LL long long int #define MAX 1600 using namespace std; LL dp[3][MAX]; int main(){ LL T,n,x,y,z,t; LL ans=0,best; while(~scanf("%I64d",&T)){ for(int cas=1;cas<=T;cas++){ scanf("%I64d %I64d %I64d %I64d %I64d",&n,&x,&y,&z,&t); ans=n*t*x; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ int cur=i%2; int pas=(i+1)%2; dp[cur][0]=0; best=(i*z+t)*x*(n-i);//注意这个地方也需要处理,开始我就搞忘了 if(best>ans) ans=best; for(int j=1;j<=i;j++){//表示持续伤害的塔的个数 if(j==i) {//i==j时要特殊处理,dp[i-1][i]这种状况不存在。只能是从dp[i-1][i-1]到dp[i][i] dp[cur][j]=(dp[pas][j-1]+((i-j)*z+t)*(j-1)*y); }else { dp[cur][j]=max((dp[pas][j]+((i-j-1)*z+t)*(j*y)),(dp[pas][j-1]+((i-j)*z+t)*(j-1)*y)); } best=dp[cur][j]+(n-i)*(x+j*y)*((i-j)*z+t); if(best>ans) ans=best; } } printf("Case #%d: %I64d\n",cas,ans); } } return 0; }
计算机在做四则运算的时候,括号,加减乘除法的优先顺序也和笔算的优先级是一样的?(忘大牛指点)
开始n,x,y,z,t是int型的,在计算的过程中爆int了,我就进行了一下强转。
在什么地方开始转的呢?
按照四则运算的优先级的顺序算的时候,什么地方可能开始爆int,就把它转成Long Long int,
在后面计算的过程中,编译器会自动把int转化为long long int进行运算。
最后AC掉了
计算机进行四则运算的优先级和人是一样的。要是强转的话,就转优先级最高处就好啦?
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #define LL long long int #define MAX 1600 using namespace std; LL dp[3][MAX]; int main(){ int T,n,x,y,z,t; LL ans=0,best; while(~scanf("%d",&T)){ for(int cas=1;cas<=T;cas++){ scanf("%d %d %d %d %d",&n,&x,&y,&z,&t); ans=(LL)n*t*x; memset(dp,0,sizeof(dp)); for(int i=0;i<MAX;i++){ dp[0][i]=0; dp[1][i]=0; } for(int i=1;i<=n;i++){ int cur=i%2; int pas=(i+1)%2; dp[cur][0]=0; best=(i*z+t)*(LL)x*(n-i); if(best>ans) ans=best; for(int j=1;j<=i;j++){//表示持续伤害的塔的个数 if(j==i) { dp[cur][j]=(dp[pas][j-1]+((i-j)*(LL)z+t)*(j-1)*y); }else { dp[cur][j]=max((dp[pas][j]+((i-j-1)*(LL)z+t)*(j*y)),(dp[pas][j-1]+((i-j)*(LL)z+t)*(j-1)*y)); } best=dp[cur][j]+(n-i)*((LL)x+j*y)*((i-j)*z+t); if(best>ans) ans=best; } } printf("Case #%d: %I64d\n",cas,ans); } } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=4941
HDU 4941 Magical Forest
题意:
N*M的矩阵,有K(10^5)个位置上有水果,交换行或者列T(10^5)次。
比赛的时候,我们用的STL的map和vector一起做的。
map的key代表的是横坐标或者纵坐标,value表示的是vector的下标。这样vecor实际占的内存不会超过10^5的int。
在交换两行或者两列的时候,会修改vector[i].szie()的时间复杂度。
感觉这个做法的时间复杂度在n(10^5)-n^2之间,着看他的数据的坑爹程度了,正常的复杂度应该在10^5-10^6之间吧。
http://blog.csdn.net/lyhvoyage/article/details/38533545 可参考
#include<stdio.h> #include<map> #include<iostream> #include<vector> #define MAX 100009 using namespace std; struct node { int x; int y; int w; }a[MAX]; map <int ,int>map1; map <int ,int>map2; map<int, int>::iterator iter,iter1,iter2; vector <int> vector1[MAX]; vector <int> vector2[MAX]; int main(){ int T,N,M,K,Q; while(~scanf("%d",&T)){ for(int t=1;t<=T;t++){ map1.clear(); map2.clear(); for(int i=0;i<MAX;i++)vector1[i].clear(); for(int i=0;i<MAX;i++)vector2[i].clear(); printf("Case #%d:\n",t); scanf("%d %d %d",&N,&M,&K); for(int i=0;i<K;i++){ scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].w); if(map1.find(a[i].x)==map1.end()){ map1[a[i].x]=i; vector1[i].push_back(i); }else{ iter=map1.find(a[i].x); int tmp=iter->second; vector1[tmp].push_back(i); } if(map2.find(a[i].y)==map2.end()){ map2[a[i].y]=i; vector2[i].push_back(i); }else{ iter=map2.find(a[i].y); int tmp=iter->second; vector2[tmp].push_back(i); } } scanf("%d",&Q); int x1,x2,flag; for(int i=0;i<Q;i++){ scanf("%d %d %d",&flag,&x1,&x2); if(flag==1){ if(map1.find(x1)==map1.end()) continue; iter1=map1.find(x1); iter2=map1.find(x2); int tmp1=iter1->second; int tmp2=iter2->second; int cc1=vector1[tmp1].size(); int cc2=vector1[tmp2].size(); for(int j=0;j<cc1;j++){ a[vector1[tmp1][j]].x=x2; } for(int j=0;j<cc2;j++){ a[vector1[tmp2][j]].x=x1; } vector1[tmp1].swap(vector1[tmp2]); } if(flag==2){ if(map2.find(x1)==map2.end())continue; iter1=map2.find(x1); iter2=map2.find(x2); int tmp1=iter1->second; int tmp2=iter2->second; int cc1=vector2[tmp1].size(); int cc2=vector2[tmp2].size(); for(int j=0;j<cc1;j++){ a[vector2[tmp1][j]].y=x2; } for(int j=0;j<cc2;j++){ a[vector2[tmp2][j]].y=x1; } vector2[tmp1].swap(vector2[tmp2]); } if(flag==3){ bool ok=false; iter=map1.find(x1); int tmp=iter->second; int siz=vector1[tmp].size(); for(int j=0;j<siz;j++){ int cc=vector1[tmp][j]; if(a[cc].y==x2) { ok=true; printf("%d\n",a[vector1[tmp][j]].w); break; } } if(ok==false) printf("0\n"); } } } } return 0; } /* 4 4 16 1 1 1 1 2 2 1 3 3 1 4 4 2 1 5 2 2 6 2 3 7 2 4 8 3 1 9 3 2 10 3 3 11 3 4 12 4 1 13 4 2 14 4 3 15 4 4 16 6 1 1 2 2 1 2 3 2 2 3 3 2 3 3 5 1 1 1 1 3 2 2 1 3 2 2 4 3 3 5 5 */
HDU 4937 Lucky Number 题解
题意:
Love_Kid将3,4,5,6认为是幸运数字。给定一个十进制数n。现在可以讲起任意转换成其他进制,但转换后的数必须是由3,4,5,6构成的,而这个进制称为幸运进制。问有多少个幸运进制。若有无数个,则输出-1。例如19在5进制下是34,所以5是幸运进制。
题解:
1.对于只有一位数的情况,显然3、4、5、6都应该输出-1.
2.如果有2位数,假设这2位中高位为a,低位为b,进制为base,则 n = a * base + b,解一元一次方程即可。
3. 如果有3位数,假设这3为从高到低分别为a、b、c,进制为base,则 n = a * base * base + b * base + c,即一元二次方程即可。
4.如果位数>= 4,可以暴力枚举进制数。base>min(3,4,5,6),所以从base=4开始枚举。又因为 x1 + x2 * base
+ x3 * base * base + x4 * base *base *base + ……>= 3*7000+3 *7000 ^2 +3 * 7000 ^3 = 1.029e12 > max(n).
所以枚举4到7000就可以了。(i*i*i<n)
总结:本题的数据的大小在200组左右,每个数据的<10^12,把只有1,2,3位的书特殊处理后,其他的暴力枚举时间复杂度刚好可以控制在100*10000之内。
本题转化成一元二次方程来解题也是很妙的想法。
#include<stdio.h> #include<math.h> #define LL long long int #define INF 7009 int main(){ LL T,n,ans; while(~scanf("%I64d",&T)){ for(LL cas=1;cas<=T;cas++){ scanf("%I64d",&n); ans=0; if(n>=3&&n<=6){ printf("Case #%I64d: -1\n",cas); continue; } for(LL i=3;i<=6;i++){ for(LL j=3;j<=6;j++){ if((n-i)/j>i&&(n-i)/j>j&&(n-i)%j==0){//解一次方程 ans++; } } } for(LL i=3;i<=6;i++){ for(LL j=3;j<=6;j++){ for(LL k=3;k<=6;k++){ LL a=i; LL b=j; LL c=k-n; LL tmp=sqrt(b*b-4*a*c); if(tmp*tmp!=b*b-4*a*c) continue;//说明灯儿塔(b^2-4*a*c)是否为整数 if((tmp-b)%(2*a)!=0) continue;//说明base是不是整数.如果 a,b,c为这种组合时,base没有整数解 LL base=(tmp-b)/(2*a); if(base>i&&base>j&&base>k) ans++; } } } for(LL i=4;i*i*i<=n;i++){//i*i*i限制了,肯定是大于等于4位的 LL tmp=n; while(tmp%i<i&&tmp%i>=3&&tmp%i<=6){ tmp=tmp/i; } if(!tmp) ans++; } printf("Case #%I64d: %I64d\n",cas,ans); } } return 0; }
相关文章推荐
- 2014 Multi-University Training Contest 9#6
- hdu 4973 A simple simulation problem 2014 Multi-University Training Contest 10
- 2014 Multi-University Training Contest 1 题解
- hdu4870 Rating 2014 Multi-University Training Contest 1
- 【2014 Multi-University Training Contest 3 1007】/【HDU 4893】 Wow! Such Sequence!
- 【2014 Multi-University Training Contest 3 1002】/【HDU 4888】 Redraw Beautiful Drawings
- hdu4915 Parenthese sequence 2014 Multi-University Training Contest 5
- 2014 Multi-University Training Contest 5
- hdu 4937 Lucky Number 2014 Multi-University Training Contest 7
- HDU 4938 Seeing People(2014 Multi-University Training Contest 7)
- hdu 4961 Boring Sum--2014 Multi-University Training Contest 9
- hdu 4946 2014 Multi-University Training Contest 8
- hdu 4915 Parenthese sequence--2014 Multi-University Training Contest 5
- hdu 4960 Another OCD Patient 2014 Multi-University Training Contest 9
- hdu 4961 Boring Sum 2014 Multi-University Training Contest 9
- 【2014 Multi-University Training Contest 3 1002】/【HDU 4888】 Redraw Beautiful Drawings
- 2014 Multi-University Training Contest 1/HDU4861_Couple doubi(数论/规律)
- 2014 Multi-University Training Contest 1
- 【2014 Multi-University Training Contest 3 1007】/【HDU 4893】 Wow! Such Sequence!
- 2014 Multi-University Training Contest 5 HDOJ 4911 Inversion