hdu 计算机学院大学生程序设计竞赛(2015’11)
搬砖
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 5134 Accepted Submission(s): 1288
那时的小明还没剪去长发,没有信用卡没有她,没有24小时热水的家,可当初的小明是那么快乐,尽管甚至没有一把破木吉他…
之所以快乐,是因为那时的小明心怀逆袭梦想。有一天,小明为了给他心目中的女神买生日礼物,来到了某建筑工地搬砖挣钱。就在这个时候,工地上又运来了一卡车的砖,包工头让小明把卡车卸下来的那堆砖分成一块一块的(要求任何2块转都要分开)。作为资深搬运工,小明总是每次将一堆砖分为两堆,这时候,所消耗的体力是分完之后两堆砖数目的差值。
现在,已知卡车运来的砖的数目,请告诉小明最少要花费多少体力才能完成包工头所要求的任务呢?
接下来T行每行一个正整数N(N<=10000000),表示卡车运来的砖块的数目。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 100000 14 using namespace std; 15 int T,n,a[2],num[2],sum; 16 int main() 17 { 18 //freopen("/home/user/桌面/in","r",stdin); 19 scanf("%d",&T); 20 while(T--) 21 { 22 scanf("%d",&n); 23 if(n==1) 24 { 25 puts("0"); 26 continue; 27 } 28 sum=a[0]=a[1]=num[0]=num[1]=0; 29 if(n&1) a[1]=n,num[1]=1,a[0]=n-1,num[0]=0; 30 else a[0]=n,num[0]=1,a[1]=n+1,num[1]=0; 31 while(a[0]!=1) 32 { 33 //printf("%d %d %d %d\n",a[0],a[1],num[0],num[1]); 34 if(a[0]&1) sum+=num[0]; 35 if(a[1]&1) sum+=num[1]; 36 if(a[0]&1) 37 { 38 num[1]=(num[1]<<1)+num[0]; 39 } 40 else 41 { 42 num[0]=(num[0]<<1)+num[1]; 43 } 44 a[0]>>=1; 45 a[1]=a[0]+1; 46 } 47 printf("%d\n",sum); 48 } 49 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 50 return 0; 51 }
投币洗衣机
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6165 Accepted Submission(s): 1585
小明作为经常参加训练的ACM队员,非常忙(Lan)碌(Duo),当然非常乐意把衣服丢给洗衣机解决啦。根据要洗的衣服数量,投币洗衣机每次需要投入2-4 枚硬币。
小明是一个非常容易出汗的男生,夏天就要到了,每天都要洗澡,所以也就有大量衣服需要洗。
小明是这么制定投币洗衣机计划的:当屯积的衣服数量大于等于a且小于b的时候,他就会马上全部拿去给洗衣机洗,并且投入2枚硬币;当屯积的衣服数量大于等于b且小于c的时候,他就会马上全部拿去给洗衣机洗,并且投入3枚硬币;当屯积的衣服数量大于等于c的时候,他就会马上全部拿去给洗衣机洗,并且投入4枚硬币。其他细节见样例。
现在知道,小明过去n 天每天换下的衣服数量v件,需要你帮忙计算出小明在过去这段时间洗衣服一共花了多少钱。
每组数据第一行是4个正整数 n (1<=n<=10000) 、a 、b 、c (1<=a<b<c<=300),具体含义见题目描述。
每组数据第二行包含n个正整数,按顺序表示过去n天每天产生的衣服数量v(1<=v<=1000)。
每组输出占一行。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 100000 14 using namespace std; 15 int n,a,b,c,x,sum,money; 16 int main() 17 { 18 //freopen("/home/user/桌面/in","r",stdin); 19 while(scanf("%d%d%d%d",&n,&a,&b,&c)==4) 20 { 21 sum=money=0; 22 while(n--) 23 { 24 scanf("%d",&x); 25 sum+=x; 26 if(sum>=a&&sum<b) 27 { 28 sum=0; 29 money+=2; 30 } 31 else if(sum>=b&&sum<c) 32 { 33 sum=0; 34 money+=3; 35 } 36 else if(sum>=c) 37 { 38 sum=0; 39 money+=4; 40 } 41 } 42 printf("%d\n",money); 43 } 44 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 45 return 0; 46 }
玩骰子
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1219 Accepted Submission(s): 369
Problem Description
终于有一天,他们决定用骰子来一决高下!
一般的骰子玩法已经不足以体现他们的水平了,于是他们自创了一套玩法来PK:
首先,每人掷3个骰子;之后,可以选择其中一个骰子重新掷(当然也可以放弃这一步),最后,比较投掷结果的大小,结果大的那方获胜,一样的话为平局。
大小比较规则为:
三个一样数字的骰子称为三条;两个一样数字的骰子称为对子;只有一个数字的骰子成为散牌。三条>对子>散牌。当双方结果都为三条时,直接比较三条数字的大小;都有对子时,先比较对子数字的大小,若相同,再比较剩下的骰子的数字的大小;都只有散牌时,先比较最大的数字的大小,若相同,再比较次大的数字的大小,还相同,最后比较最小的数字的大小。
现在Nias已经投了3个骰子,还剩一次机会可以选择其中一个骰子重新投(或不选),而且他已经知道了Ains的最后投掷结果,求Nias获胜的概率有多大。
接下来T行,每行6个1~6的整数,前三个表示Nias第一次的投掷结果,后三个表示Aias最终的投掷结果。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 100000 14 using namespace std; 15 int T,a[3],b[3]; 16 int cmp(int*a,int*b) 17 { 18 // printf("%d %d %d %d %d %d\n",a[0],a[1],a[2],b[0],b[1],b[2]); 19 int c[7],d[7]; 20 memset(c,0,sizeof(c)); 21 memset(d,0,sizeof(d)); 22 c[a[0]]++;c[a[1]]++;c[a[2]]++; 23 d[b[0]]++;d[b[1]]++;d[b[2]]++; 24 int m1=0,m2=0,i1,i2; 25 for(int i=1;i<=6;i++) m1=max(m1,c[i]); 26 for(int i=1;i<=6;i++) m2=max(m2,d[i]); 27 // printf("%d %d\n",m1,m2); 28 if(m1!=m2) return m1-m2; 29 for(i1=6;i1>0;i1--) if(c[i1]==m1) break; 30 for(i2=6;i2>0;i2--) if(d[i2]==m2) break; 31 // printf("%d %d\n",i1,i2); 32 if(i1!=i2||m1==3) return i1-i2; 33 c[i1]=d[i2]=0; 34 for(i1=6;i1>0;i1--) if(c[i1]) break; 35 for(i2=6;i2>0;i2--) if(d[i2]) break; 36 // printf("%d %d\n",i1,i2); 37 if(i1!=i2||m1==2) return i1-i2; 38 c[i1]=d[i2]=0; 39 for(i1=6;i1>0;i1--) if(c[i1]) break; 40 for(i2=6;i2>0;i2--) if(d[i2]) break; 41 // printf("%d %d\n",i1,i2); 42 return i1-i2; 43 } 44 int main() 45 { 46 //freopen("/home/user/桌面/in","r",stdin); 47 scanf("%d",&T); 48 while(T--) 49 { 50 scanf("%d%d%d",&a[0],&a[1],&a[2]); 51 scanf("%d%d%d",&b[0],&b[1],&b[2]); 52 if(cmp(a,b)>0) 53 { 54 printf("%.3lf\n",1.0); 55 continue; 56 } 57 int c,maxc=0,a1[3]; 58 for(int i=0;i<3;i++) 59 { 60 memcpy(a1,a,sizeof(a)); 61 c=0; 62 for(int j=1;j<=6;j++) 63 { 64 a1[i]=j; 65 if(cmp(a1,b)>0) c++; 66 } 67 // printf("%d\n",c); 68 maxc=max(c,maxc); 69 } 70 printf("%.3lf\n",maxc/6.0); 71 } 72 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 73 return 0; 74 }
质方数
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3655 Accepted Submission(s): 1228
Problem Description
现在,小明慢慢长大了,但依然很喜欢数字,最近,他迷上了质数和平方数,并且自己把质数的平方命名为“质方数”。
现在,他在研究这样一个问题:距离一个正整数N最接近的质方数是多少?
接下来T行,每行输入一个正整数N(1<=N<=10^8)。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 11000 14 using namespace std; 15 int T,n,zfs[MAX+10],zn,notpri[MAX]; 16 void init() 17 { 18 memset(notpri,0,sizeof(notpri)); 19 zfs[0]=-MAX; 20 zn=1; 21 for(int i=2;i<=MAX;i++) 22 if(!notpri[i]) for(int j=i*i;j<=MAX;j+=i) notpri[j]=1; 23 for(int i=2;i<=MAX;i++) if(!notpri[i]) zfs[zn++]=i*i; 24 } 25 int main() 26 { 27 //freopen("/home/user/桌面/in","r",stdin); 28 init(); 29 scanf("%d",&T); 30 while(T--) 31 { 32 scanf("%d",&n); 33 int *a=lower_bound(zfs,zfs+zn,n); 34 printf("%d\n",*a-n>n-*(a-1)?*(a-1):*a); 35 } 36 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 37 return 0; 38 }
ACM组队安排
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1051 Accepted Submission(s): 512
杭州电子科技大学ACM集训队也准备开始组队。
教练想把所有的n个队员组成若干支队伍,原则是每支队伍至少一人,最多三人。
现在问题来了:如果已知集训队队员的数量n,请你帮教练计算出所有可能的组队方案有多少种。
特别说明:
队伍没有编号,即如果有A,B,C三人,{A}{BC}与{BC}{A}是同一种组队情况。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 100000 14 using namespace std; 15 long long d[4][21],c[21][4]; 16 int n; 17 long long A(int m,int n) 18 { 19 long long ans=1; 20 for(;n>0;n--,m--) ans*=m; 21 return ans; 22 } 23 long long C(int m,int n) 24 { 25 return A(m,n)/A(n,n); 26 } 27 void init() 28 { 29 memset(d,0,sizeof(d)); 30 for(int i=0;i<=20;i+=3) 31 { 32 d[3][i]=A(i,i)/A(i/3,i/3); 33 for(int j=0;j<i;j+=3) d[3][i]/=A(3,3); 34 // printf("%lld %lld %lld %lld\n",A(i,i),i/3*A(3,3),A(i/3,i/3),d[3][i]); 35 } 36 // for(int i=0;i<=20;i++) printf("%lld ",d[3][i]);printf("\n"); 37 for(int i=0;i<=20;i++) 38 { 39 long long t; 40 for(int j=0;j<=i;j+=2) 41 { 42 t=A(i,j)/A(j/2,j/2); 43 for(int k=0;k<j;k+=2) t/=A(2,2); 44 d[2][i]+=t*d[3][i-j]; 45 } 46 } 47 // for(int i=0;i<=20;i++) printf("%lld ",d[2][i]);printf("\n"); 48 for(int i=0;i<=20;i++) 49 { 50 long long t; 51 for(int j=i;j>=0;j--) 52 { 53 t=A(i,j)/A(j,j); 54 d[1][i]+=t*d[2][i-j]; 55 } 56 } 57 // for(int i=0;i<=20;i++) printf("%lld ",d[1][i]);printf("\n"); 58 } 59 int main() 60 { 61 //freopen("/home/user/桌面/in","r",stdin); 62 init(); 63 while(scanf("%d",&n)==1&&n) printf("%lld\n",d[1][n]); 64 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 65 return 0; 66 }
逆袭指数
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1868 Accepted Submission(s): 379
尽管身处逆境,但小明一直没有放弃努力,除了搬砖,小明还研究过东方的八卦以及西方的星座,一直试图在命理上找到自己能够逆袭的依据。
当这些都失败以后,小明转向了数学研究,希望从中得到一些信息。一天,小明在研究《BestCoder逆袭的数理基础》这本书时,发现了宝贵的信息,其中写道:
每个人都存在一个逆袭指数,对于这个逆袭指数,可能存在连续的因子,如果这个连续因子足够长的话,那么这个人逆袭的概率就很大!
小明已知自己的逆袭指数,请告诉小明他最长的连续因子,以让他来判断他自己是否能够逆袭。
每组数据占一行,包含一个整数N,表示小明的逆袭指数,N小于2^31。
第一行输出最长的因子个数;
第二行输出最小的因子序列,具体请参考样例.
特别说明:由于小明十分讨厌单身,所以1不算因子。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 0x7fffffff 14 using namespace std; 15 long long a[13][2000],a2[50000]; 16 int n,an[14]; 17 int main() 18 { 19 //freopen("/home/user/桌面/in","r",stdin); 20 a2[3]=6; 21 for(an[2]=4;a2[an[2]-1]<=MAX;an[2]++) a2[an[2]]=a2[an[2]-1]/(an[2]-2)*an[2]; 22 an[2]--; 23 // printf("%d %d\n",a2[an[2]],a[2][an[2]-1]); 24 //for(int i=3;i<100;i++) printf("%lld ",a2[i]);printf("\n"); 25 for(int i=3,j;i<=12;i++) 26 { 27 a[i][1]=1; 28 for(j=2;j<i+2;j++) a[i][j]=j*a[i][j-1]; 29 //printf("%d\n",(int)a[i][j-1]); 30 for(;a[i][j-1]<=MAX;j++) a[i][j]=a[i][j-1]/(j-i)*j; 31 an[i]=j-1; 32 // printf("%d %d\n",a[i][an[i]],a[i][an[i]-1]); 33 //printf("%d\n",an[i]); 34 //for(int k=i+1;k<an[i];k++) printf(" %lld",a[i][k]);printf("\n"); 35 } 36 while(scanf("%d",&n)==1) 37 { 38 if(n==1) 39 { 40 printf("0\n\n"); 41 continue; 42 } 43 if(n==0) 44 { 45 printf("1\n0\n"); 46 continue; 47 } 48 int find=0; 49 for(int i=12,j;i>2;i--) 50 { 51 for(j=i+1;j<an[i]&&n>=a[i][j];j++) 52 { 53 if(n%a[i][j]==0) 54 { 55 find=1; 56 break; 57 } 58 } 59 if(find) 60 { 61 printf("%d\n%d",i,j-i+1); 62 for(int k=j-i+2;k<=j;k++) printf("*%d",k); 63 printf("\n"); 64 break; 65 } 66 } 67 if(find) continue; 68 int i; 69 for(i=3;i<an[2]&&n>=a2[i];i++) 70 { 71 if(n%a2[i]==0) 72 { 73 find=1; 74 break; 75 } 76 } 77 if(find) 78 { 79 printf("2\n%d*%d\n",i-1,i); 80 continue; 81 } 82 int m=sqrt(n); 83 for(i=2;i<=m;i++) 84 if(n%i==0) 85 { 86 find=1;break; 87 } 88 printf("1\n%d\n",find?i:n); 89 } 90 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 91 return 0; 92 }
油菜花王国
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2254 Accepted Submission(s): 581
出城不久,小明看到一大片油菜花,忍不住眼前美景的诱惑,就拐了进去,谁曾想,这一拐却误入了油菜花王国!
油菜花王国生存着一大批油菜花精灵,这是一种特别热爱斐波那契数列的生物。在这个国度里,有若干个家族,每只精灵都只属于一个家族。精灵出生时,身上都会印着一个编码,表示这只精灵的能力值,如果这个能力值正好存在于斐波那契数列,那么他就会为所在的家族增加一点威望。小明通过和精灵们聊天,知道了所有精灵之间的关系。
现在,小明想知道油菜花王国里威望值最大的家族的威望值是多少,你能帮帮他吗?小明会把精灵们之间的关系网络告诉你,由于整个关系网络实在太庞大,所以小明很有可能重复介绍其中一些关系。
每组数据第一行包含两个整数 n (1 <= n <= 1000) 、 m (1 <= m <= 5000) ,分别表示油菜花王国精灵数量和精灵之间关系组数。
第二行包含 n 个整数,表示精灵们的能力值 k (1 <= k <= 1000000000)。
接下去有 m 行,每行有两个不同的整数 u 、 v (1 <= u, v <= n) ,表示精灵 u 和精灵 v 属于同一个家族。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 1000000000 14 using namespace std; 15 int n,m,ss[1010],sum[1010];//n num of v,m num of edge 16 bool v[1010]; 17 set<int>fib; 18 void init() 19 { 20 fib.clear(); 21 int a0,a1,a2; 22 fib.insert(1); 23 a1=1;a2=2; 24 while(a2<=MAX) 25 { 26 fib.insert(a2); 27 a2=a1+a2; 28 a1=a2-a1; 29 } 30 } 31 int findset(int x) 32 { 33 return ss[x]!=x?ss[x]=findset(ss[x]):x; 34 } 35 int findset1(int x) 36 { 37 int stacks[1010],i=-1; 38 while(ss[x]!=x) 39 { 40 stacks[++i]=x; 41 x=ss[x]; 42 } 43 while(i>=0) 44 { 45 ss[stacks[i]]=x; 46 i--; 47 } 48 return x; 49 } 50 int main() 51 { 52 //freopen("/home/user/桌面/in","r",stdin); 53 init(); 54 //for(set<int>::iterator i=fib.begin();i!=fib.end();i++) printf("%d ",*i);printf("\n"); 55 while(scanf("%d%d",&n,&m)==2) 56 { 57 for(int i=1,a;i<=n;i++) 58 { 59 scanf("%d",&a); 60 fib.count(a)?v[i]=1:v[i]=0; 61 } 62 for(int i=1;i<=n;i++) ss[i]=i; 63 for(int a,b,i=0;i<m;i++) 64 { 65 scanf("%d%d",&a,&b); 66 int x,y; 67 x=findset(a);y=findset(b); 68 ss[x]=y; 69 } 70 memset(sum,0,sizeof(sum)); 71 int maxsum=-1; 72 for(int i=1;i<=n;i++) 73 { 74 int idx=findset(i); 75 sum[idx]+=v[i]; 76 } 77 for(int i=1;i<=n;i++) 78 maxsum=max(maxsum,sum[i]); 79 printf("%d\n",maxsum); 80 } 81 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 82 return 0; 83 }
游乐场
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5362 Accepted Submission(s): 857
最近,杭州刚建了一座游乐场,为了弥补儿时的遗憾,小明带了一笔钱迫不及待地要去体验一番。
由于是第一次来到这种地方,小明也不知哪些项目比较好玩,因此他想体验尽可能多的项目。来之前,小明还向朋友打听了一下关于游乐场的情况,只要是朋友推荐过的,他一定要体验。当然,每个项目都需要一定的花费,当小明的钱不够时就不能再玩了。
现在,已知小明身上的钱以及每个游戏项目的花费,请问小明最多能体验多少个项目?
对于每组数据:
第一行是三个整数n, m, k,分别表示游乐场里的游戏项目数,朋友推荐的游戏项目数,小明身上的钱数(1<=m<=n<=10000, 1<=k<=10^9)。
第二行是n个整数,第i个整数xi表示第i个游戏项目的费用(1<=xi<=10^9)。
第三行是m个整数pi,表示朋友推荐第pi个游戏项目(1<=pi<=n)。
每组输出占一行。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 10000 14 using namespace std; 15 int T,n,m,k,costs[MAX+10],cost[MAX+10],costidx[MAX+10],idx[MAX+10],vis[MAX+10]; 16 bool com(int&a,int&b) 17 { 18 return cost[a]<cost[b]; 19 } 20 int main() 21 { 22 //freopen("/home/user/桌面/in","r",stdin); 23 scanf("%d",&T); 24 while(T--) 25 { 26 scanf("%d%d%d",&n,&m,&k); 27 memset(vis,0,sizeof(vis)); 28 for(int i=1;i<=n;i++) scanf("%d",&costs[i]); 29 for(int i=0;i<m;i++) 30 { 31 scanf("%d",&idx[i]); 32 vis[idx[i]]=1; 33 costidx[i]=costs[idx[i]]; 34 } 35 int j=0; 36 for(int i=1;i<=n;i++) if(!vis[i]) cost[j++]=costs[i]; 37 sort(costidx,costidx+m); 38 sort(cost,cost+j); 39 int i,sum=0; 40 for(i=0;i<m;i++) 41 { 42 sum+=costidx[i]; 43 if(sum>k) break; 44 } 45 if(i<m) 46 { 47 puts("-1"); 48 continue; 49 } 50 n=j; 51 for(int j=0;j<n;j++) 52 { 53 sum+=cost[j]; 54 if(sum>k) break; 55 i++; 56 } 57 printf("%d\n",i); 58 } 59 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 60 return 0; 61 }