Jxnu Group Programming Ladder Tournament 2017题解
L1-1 这是一道简单题
题解:直接循环输出就好了
1 #include <iostream> 2 using namespace std; 3 int main(){ 4 cin.sync_with_stdio(false); 5 for(int i=0;i<3;i++){ 6 cout<<"DaHaoGeJiuShiYiGeRuoJi"<<endl; 7 } 8 return 0; 9 }
L1-2 叶神的字符串
题解:查找YS的字符片段,查到了就把它置为空格,遍历完了一遍以后,最后在查找有没有不是空格但是前后相同的转发片段
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 int main(){ 5 string s; 6 while(cin>>s) 7 { 8 int cnt=0; 9 for(int i=0;i<s.length()-1;i++) 10 { 11 if(s[i]=='Y'&&s[i+1]=='S') 12 cnt++,s[i]=s[i+1]=' '; 13 } 14 for(int i=0;i<s.length()-1;i++) 15 { 16 if(s[i]!=' '&&s[i]==s[i+1]) 17 { 18 cnt++; 19 break; 20 } 21 } 22 cout<<cnt<<endl; 23 } 24 return 0; 25 }
L1-3 成绩排名
题解:直接进行结构体排序就好了,处理下相同的分数的排名情况
1 #include <iostream> 2 #include <algorithm> 3 #define N 1010 4 using namespace std; 5 struct node{ 6 int id; 7 int grade[N]; 8 int sum; 9 string name; 10 }student[N]; 11 bool cmp(node a,node b){ 12 if(a.sum==b.sum){ 13 return a.id<b.id; 14 } 15 return a.sum>b.sum; 16 } 17 int main(){ 18 int n,m,num; 19 cin.sync_with_stdio(false); 20 while(cin>>n>>m){ 21 for(int i=0;i<n;i++){ 22 cin>>student[i].id>>student[i].name; 23 student[i].sum=0; 24 for(int j=0;j<m;j++){ 25 cin>>student[i].grade[j]; 26 student[i].sum+=student[i].grade[j]; 27 } 28 } 29 sort(student,student+n,cmp); 30 for(int i=0;i<n;i++){ 31 cout<<student[i].id<<" "<<student[i].name; 32 for(int j=0;j<m;j++){ 33 cout<<" "<<student[i].grade[j]; 34 } 35 if(i==0){ 36 num=1; 37 } 38 else if(student[i].sum!=student[i-1].sum){ 39 num=i+1; 40 } 41 cout<<" Sum = "<<student[i].sum<<" Ranking = "<<num<<endl; 42 } 43 } 44 return 0; 45 }
L1-4 王胖子买零食
题解:贪心,每次拿最便宜的
1 #include <iostream> 2 #include <algorithm> 3 #define N 1010 4 using namespace std; 5 struct node{ 6 int w,m; 7 }thing[N]; 8 bool cmp(node a,node b){ 9 return a.m<b.m; 10 } 11 int main(){ 12 int n,m; 13 cin.sync_with_stdio(false); 14 while(~scanf("%d %d",&n,&m)){ 15 for(int i=0;i<m;i++){ 16 scanf("%d %d",&thing[i].m,&thing[i].w); 17 } 18 sort(thing,thing+m,cmp); 19 double sum=0; 20 for(int i=0;i<m;i++){ 21 if(n>=thing[i].w*thing[i].m){ 22 sum+=thing[i].w; 23 n-=(thing[i].w*thing[i].m); 24 } 25 else{ 26 sum+=(n*1.0/thing[i].m); 27 n=0; 28 } 29 if(n==0){ 30 break; 31 } 32 } 33 printf("%.4lf\n",sum); 34 } 35 return 0; 36 }
L1-5 Dada的游戏
题解:遍历整个区间当后一个比前一个大的话就让一个计数器++;当后一个比前一个小的时候,把计数器的值和最大值进行比较并且把计数器置为1,再向后面遍历(PS:因为要连续的所以既然后一个比前一个小,当然就直接从当前去找就好了,回去的话肯定没有有现在最大值的大,所以把i置为j的值)
1 #include<iostream> 2 #include<stdio.h> 3 4 using namespace std; 5 6 int main() 7 { 8 int n; 9 int num[100005]; 10 while(~scanf("%d",&n)) 11 { 12 for(int i = 0; i < n; i++) 13 scanf("%d",&num[i]); 14 int maxx=0,i,j; 15 for(i = 0; i < n-maxx; ) 16 { 17 int temp=1; 18 for(j = i+1; j < n; j++) 19 { 20 if(num[j]>num[j-1]) 21 temp++; 22 else 23 break; 24 } 25 if(temp>maxx) 26 maxx=temp; 27 i=j;//这里要优化要不会超时 28 } 29 printf("%d\n",maxx); 30 } 31 return 0; 32 }
L1-6
吐槽:一道裸的map的题,后面考虑有人不会stl的map,所以数据开小了直接用数组映射就好了。
题解:把每层的砖块之间的缝的位置算出来放入map中,如果map里原本有的话就在那个值上++,如果没有就在map里新加入一个值为1,最后找map里值最多的,就说明打的洞就是最少的。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <map> 5 using namespace std; 6 int main(){ 7 //freopen("in.txt","r",stdin); 8 //freopen("out.txt","w",stdout); 9 int n,k; 10 11 while(scanf("%d",&n)!=EOF) 12 { 13 map<int,int> mp; 14 for(int i=0;i<n;i++) 15 { 16 scanf("%d",&k); 17 int widthCnt=0; 18 int nowWidth; 19 for(int j=0;j<k;j++) 20 { 21 scanf("%d",&nowWidth); 22 if(j!=k-1) 23 { 24 widthCnt+=nowWidth; 25 mp[widthCnt]++; 26 } 27 } 28 } 29 map<int,int>::iterator it; 30 int maxGaps=0; 31 for(it=mp.begin();it!=mp.end();it++) 32 if(maxGaps<it->second) 33 maxGaps=it->second; 34 printf("%d\n",n-maxGaps); 35 } 36 return 0; 37 }
L2-1 N!
题解:有两种办法,一个是用c++的高精度来写,第二种是用long long int去存乘积,但是不要全部都存,把计算过程中所有的因子10提取出来(PS:sum只存去除后缀0的数),就是说例如如果遇到了5,就把sum除以2,把标志末尾有多少个0的计数器++,最后吧sum输出,在循环输出全部的0。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <map> 5 #define LL long long int 6 using namespace std; 7 8 int main(){ 9 //freopen("in.txt","r",stdin); 10 //freopen("out.txt","w",stdout); 11 LL n; 12 while(cin>>n) 13 { 14 LL pre=1; 15 string s=""; 16 for(int i=2;i<=n;i++) 17 { 18 int x=i; 19 while(x%5==0) 20 { 21 if(x%2==0) 22 x/=2; 23 else 24 pre/=2; 25 x/=5; 26 s+='0'; 27 } 28 pre*=x; 29 } 30 cout<<pre<<s<<endl; 31 32 } 33 return 0; 34 }
L2-2 日天的终生大事
题解:
这道题目可以从递推的角度来分析,
对于任何一个L位K进制数,可以由一个L-1位K进制数(这里考虑前导0,因为无论多少前导0,都可以在首部加入非0数字使其合法)在首部加上一个数组合而成。
所以构建递推状态dp[i][j]//表示i位,首部为数字j的数的种类。那么可以推导公式:dp[i][j]=dp[i-1][x]-dp[i-1][j-1]-dp[i-1][j+1] (0<=x<k),此处dp[i-1][x]为x各种取值下的求和。计算完后还得按题目要求去除数字和它相邻的情况。
最后对L位以1~k-1的状态求和即可。
代码还需要处理几个点:
1、做减法后可能为负数,要处理成正数。
2、左右不一定都存在数字,要根据j判断。
3、用循环求和会多出k的复杂度,因为在先前以及依次求出了dp[i-1][x],所以用sum累计一下,直接就可以在求解dp[i][j]时使用。
4、虽然对于大部分数,不能有前导0,所以最后求和时,不考虑dp[L][0],但是对于位数为1时,需要累计dp[1][0]。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <map> 5 #include <algorithm> 6 #define LL long long int 7 using namespace std; 8 LL dp[1005][1005]; 9 const LL mod=1000000007LL; 10 int main(){ 11 12 //freopen("in.txt","r",stdin); 13 cin.sync_with_stdio(false); 14 LL k,l; 15 while(cin>>k>>l) 16 { 17 LL sum=0; 18 for(int i=0;i<k;i++) 19 dp[1][i]=1,sum++; 20 dp[1][k]=0; 21 22 for(int i=2;i<=l;i++) 23 { 24 LL temp=0; 25 for(int j=0;j<k;j++) 26 { 27 dp[i][j]=sum; 28 if(j==0) 29 dp[i][j]-=dp[i-1][j+1]; 30 else 31 dp[i][j]-=(dp[i-1][j-1]+dp[i-1][j+1]); 32 dp[i][j]=(dp[i][j]+3*mod)%mod; 33 temp+=dp[i][j]; 34 temp%=mod; 35 } 36 dp[i][k]=0; 37 sum=temp; 38 } 39 sum=0; 40 for(int i=l==1?0:1;i<k;i++) 41 { 42 sum+=dp[l][i],sum%=mod; 43 } 44 cout<<sum<<endl; 45 } 46 return 0; 47 }
2017-05-02 20:44:07