苏州大学ICPC集训队新生赛第二场

A-Sorce:

题意:给一个字符串(只含有‘O’和'X'),如果包含连续'O'那么从第一个O开始分数从1开始按照公差为1的等差数列递增如“OOO”那么分数为1+2+3,如果遇到'X'那么下个'O'又从1开始,如“OOXOO”,分数为1+2+1+2。

分析:水题,直接上代码。

苏州大学ICPC集训队新生赛第二场
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int t;
 5     string str;
 6     scanf("%d",&t);
 7     while (t--){
 8         cin>>str;
 9         int ans = 0,cnt = 1;
10         for (int i = 0; i < str.size(); i++){
11             if (str[i] == 'O') ans += cnt++;
12             else cnt = 1;
13         }
14         printf("%d\n",ans);
15     }
16     return 0;
17 }
View Code

B-Tetrahedron:

题意:给一个四面体,顶点为A,B,C,D,刚开始位于D点,输入一个n,问从D出发向其他顶点移动n步又回到D总共有多少种方案,结果取余1e9+7。

分析:如果说第n步回到了D点,那么第n-1步一定不在D点,那么所有第n-1到达不在D点的点的方案数之和就是第n步到达d点的方案数,由此可以想到用dp求解。

设D编号为0,A编号为1,B编号为2,C编号为3,dp[i][j]为第i步到达j号节点的方案数。那么显然有转移方程:dp[i][j] = sum(dp[i-1][k])其中k != j。

最后只需要求出 dp[n][0]表示第n步到D节点的方案数就好了。

苏州大学ICPC集训队新生赛第二场
 1 #include<cstdio>
 2 using namespace std;
 3 const int maxn = 1e7+5;
 4 const int mod = 1e9+7;
 5 int dp[maxn][4];
 6 int n;
 7 int main(){
 8     scanf("%d",&n);
 9     dp[1][0] = 0;
10     dp[1][1] = dp[1][2] = dp[1][3] = 1;
11     for (int i = 1; i <= n; i++){
12         for (int j = 0; j < 4; j++){
13             for (int k = 0; k < 4; k++){
14                 if (j == k) continue;
15                 dp[i][j] += dp[i-1][k];
16                 dp[i][j] %= mod;                    
17             }
18         }
19     }
20     printf("%d",dp[n][0]);
21     return 0;
22 }
View Code

F-Squares:

题意:开始看了半天没看懂,后来mqf分析后发现是水题,就是先输入一个n再输入一个k,然后输入n个数字(a1,a2……an),找出一个点包含于k个  (0,0)点与(ai,ai)点组成的正方形  之内。

分析:水题,直接上代码。

苏州大学ICPC集训队新生赛第二场
#include<bits/stdc++.h>
using namespace std;
int arr[55];
int main(){
    int n,k;
    scanf("%d %d",&n,&k);
    for (int i = 0; i < n; i++) scanf("%d",&arr[i]);
    if (k>n) printf("-1");
    else{
        sort(arr,arr+n);
        printf("%d %d",arr[n-k],arr[n-k]);
    }
    return 0;
}
View Code

G - Jumping Jack:

题意:初始位于0,给一个坐标n,每次可以向左或者向右跳,跳的距离为(1,2,3,4,5……)也就是下一次跳的距离比这次多1,第一次跳的距离是1,问跳到n最少要几次。

分析:乍一看很像搜索,但范围太广,MLE。后经mqf分析应该是数学思维题。赛后想了挺久没想出来,于是看了一下题解。。。

首先给的n可以是负数,但可以根据对称性把所有情况都化为n为正数的情况,也就是如果n为负数就把n变为-n。

此时我们从0点向右走,要在最短的步数内到达n,当然是要朝着n的方向走。我们一直朝着n走,可能会很幸运刚好走到n,但通常情况下我们不会那么凑巧刚好走到n,而是会走到某处,

当我们再跳一次时就会超过n,此时需要借助向左跳来处理这种情况。

我们先来分析一下向左跳一次会得到什么结果:

苏州大学ICPC集训队新生赛第二场

那么也就是说,向左跳一次再向右跳会相对于一直向右跳减少2的倍数的距离,那么如果我们跳到某处时再跳一步就超过n,而超过n的距离刚好是个偶数

那么我们完全可以通过在之前的某处回跳一次在接着往右跳使得我们恰好能够跳到n,下面的图片分析:

苏州大学ICPC集训队新生赛第二场

如果超过n的距离是一个奇数,那么我们则需要先把他处理成一个偶数,再在中间的某个步骤中回跳一次。那么如何处理呢?

处理方法是接着往右跳,拉大与n的距离,当与n的距离变为一个偶数时遍可以转化为上一种情况。

实际上只需要往右跳1步(接下来跳的步数是奇数)数或者2步(接下来跳的步数是偶数),下面是图片分析:

苏州大学ICPC集训队新生赛第二场

下面是具体代码实现:

苏州大学ICPC集训队新生赛第二场
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int x;
 5     scanf("%d",&x);
 6     if (x < 0)x = -x;
 7     if (x == 0) printf("0\n");
 8     else{
 9         int step = 1,pos = 0,cnt = 0;
10         while (pos < x){
11             pos += step++;
12             cnt++;
13         }
14         if (pos==x) printf("%d\n",cnt);
15         else if ((pos-x)%2==0) printf("%d\n",cnt);
16         else{
17             if ((pos-x+step)%2==0) printf("%d\n",cnt+1);
18             else printf("%d\n",cnt+2);
19         }
20     }
21     return 0;
22 }
View Code

 

上一篇:centos6.8 环境一键安装包 nginx配置thinkphp5


下一篇:苏州大学ICPC集训队新生赛第二场