2018年浙江中医药大学程序设计竞赛 Solution

Problem A. Jhadgre的C语言程序

签。

1 #include <bits/stdc++.h>
2 using namespace std;
3   
4 int main()
5 {
6     puts("Helle World!");
7     return 0;
8 }  
View Code

 

Problem B. Wpremig的AH之战

Solved.

  • 如果 $n >= m 直接赢$
  • 否则 $易知必败局面是当前剩余数是(n + 1)的倍数$
 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 int n, m;
 6  
 7 int main()
 8 {
 9     while(~scanf("%d %d", &n, &m))
10     {
11         if(n >= m)
12         {
13             for(int i = m; i <= n; ++i)
14                 printf("%d%c", i, " \n"[i == n]);
15         }
16         else
17         {
18             if(m % (n + 1) == 0) puts("You are loser");
19             else printf("%d\n", m % (n + 1));
20         }
21     }
22     return 0;
23 }
View Code

 

Problem D. Jhadgre的梯子

温暖的签。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define ll long long
 5 #define N 100010
 6 int n;
 7 ll m, x, Max;
 8  
 9 int main()
10 {
11     while (scanf("%d%lld", &n, &m) != EOF)
12     {
13         Max = 0;
14         for (int i = 1; i <= n; ++i)
15         {
16             scanf("%lld", &x);
17             Max = max(Max, x);
18         }
19         printf("%lld\n", max(0ll, Max - m));
20     }
21     return 0;
22 }
View Code

 

 Problem E. Jhadgre的合唱队形

Solved.

题意:

有$n个队列,两种操作$

  • $1\; x\; y\; z \;\;将编号属于[x, y]的队列最后加入一个z$
  • $2\; x\; y\; z \;\; 询问编号属于[x, y]的所有队列中的所有人中第z大的数是多少$

思路:

本来想分块维护三个BIT,但是发现空间炸了。

那找第$k大的数可以二分,多次询问,就整体二分$

对于每个询问二分答案,在时间线中,在你前面的 并且 值小于你二分的答案就加入线段树

查询的时候直接查,记得更新k,然后将询问分组即可

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 #define ll long long
  5 #define N 50010
  6 int n, m, Q;
  7  
  8 namespace SEG
  9 {
 10     ll sum[N << 2], lazy[N << 2];
 11     void pushdown(int id, int l, int mid, int r)
 12     {
 13         if (!lazy[id]) return;
 14         sum[id << 1] += 1ll * (mid - l + 1) * lazy[id];
 15         lazy[id << 1] += lazy[id];
 16         sum[id << 1 | 1] += 1ll * (r - mid) * lazy[id];
 17         lazy[id << 1 | 1] += lazy[id];
 18         lazy[id] = 0;
 19     }
 20     void update(int id, int l, int r, int ql, int qr, int v)
 21     {
 22         if (l >= ql && r <= qr)
 23         {
 24             sum[id] += 1ll * v * (r - l + 1);
 25             lazy[id] += v;
 26             return;
 27         }
 28         int mid = (l + r) >> 1;
 29         pushdown(id, l, mid, r);
 30         if (ql <= mid) update(id << 1, l, mid, ql, qr, v);
 31         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v);
 32         sum[id] = sum[id << 1] + sum[id << 1 | 1];
 33     }
 34     ll query(int id, int l, int r, int ql, int qr)
 35     {
 36 //      printf("%d %d %d %d\n", l, r, ql, qr);
 37         if (l >= ql && r <= qr) return sum[id];
 38         int mid = (l + r) >> 1;
 39         pushdown(id, l, mid, r);
 40         ll res = 0;
 41         if (ql <= mid) res += query(id << 1, l, mid, ql, qr);
 42         if (qr > mid) res += query(id << 1 | 1, mid + 1, r, ql, qr);
 43         return res;
 44     }
 45 }
 46  
 47 struct node
 48 {
 49     int op, l, r, z, id;
 50     node () {}
 51     node (int op, int l, int r, int z, int id) : op(op), l(l), r(r), z(z), id(id) {}    
 52 }q[N << 1], ql[N << 1], qr[N << 1];
 53 int ans[N];
 54  
 55 void CDQ(int L, int R, int l, int r)
 56 {
 57     if (L > R) return;
 58     if (l == r)
 59     {
 60         for (int i = L; i <= R; ++i) if (q[i].op == 2)
 61             ans[q[i].id] = l;
 62         return;
 63     }
 64     int mid = (l + r) >> 1;
 65     int cnt_ql = 0, cnt_qr = 0;
 66     for (int i = L; i <= R; ++i)
 67     {
 68         if (q[i].op == 1)
 69         {
 70             if (q[i].z <= mid)
 71             {
 72                 SEG::update(1, 1, n, q[i].l, q[i].r, 1);
 73                 ql[++cnt_ql] = q[i];
 74             }
 75             else
 76                 qr[++cnt_qr] = q[i];
 77         }
 78         else
 79         {
 80             ll sze = SEG::query(1, 1, n, q[i].l, q[i].r);
 81             if (sze < q[i].z)
 82             {
 83                 q[i].z -= sze;
 84                 qr[++cnt_qr] = q[i];
 85             }
 86             else
 87                 ql[++cnt_ql] = q[i];
 88         }
 89     }
 90     for (int i = 1; i <= cnt_ql; ++i) if (ql[i].z <= mid) SEG::update(1, 1, n, ql[i].l, ql[i].r, -1);
 91     for (int i = 1; i <= cnt_ql; ++i) q[L + i - 1] = ql[i];
 92     for (int i = 1; i <= cnt_qr; ++i) q[L + cnt_ql + i - 1] = qr[i];
 93     CDQ(L, L + cnt_ql - 1, l, mid);
 94     CDQ(L + cnt_ql, R, mid + 1, r);
 95 }
 96  
 97 int main()
 98 {
 99     while (scanf("%d%d", &n, &Q) != EOF)
100     {
101         m = 0;
102         memset(ans, 0, sizeof ans);
103         for (int i = 1, op, x, y, z; i <= Q; ++i)
104         {
105             scanf("%d%d%d%d", &op, &x, &y, &z);
106             if (op == 1) q[++m] = node(1, x, y, -z, i);
107             else q[++m] = node(2, x, y, z, i);
108         }
109         CDQ(1, m, -n, -1);
110         for (int i = 1; i <= Q; ++i) if (ans[i])
111             printf("%d\n", -ans[i]);
112     }
113     return 0;
114 }  
View Code

 

Problem F. Jhadgre的伤心地

演了一波,小dp写成最短路、搜索可还行

 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 typedef long long ll;
 6  
 7 const int maxn = 1e3 + 10;
 8  
 9 int n;
10 ll a[maxn];
11 ll dis[maxn];
12 int vis[maxn];
13  
14 void BFS()
15 {
16     memset(vis, 0, sizeof vis);
17     memset(dis, 0x3f, sizeof dis);
18     vis[1] = 1;
19     dis[1] = 0;
20     queue<int>q;
21     q.push(1);
22     while(!q.empty())
23     {
24         int u = q.front();
25         q.pop();
26         if(!vis[min(n, u + 5)])
27         {
28             dis[min(n, u + 5)] = dis[u] + 2;
29             vis[min(n, u + 5)] = 1;
30             q.push(min(n, u + 5));
31         }
32          
33         if(!vis[min(n * 1ll, a[u])])
34         {
35             dis[min(n * 1ll, a[u])] = dis[u] + 2;
36             vis[min(n * 1ll, a[u])] = 1;
37             q.push(min(n * 1ll, a[u]));
38         }
39     }
40 }
41  
42 int main()
43 {
44     while(~scanf("%d", &n))
45     {
46         n++;
47         for(int i = 1; i <= n - 1; ++i)
48         {
49             scanf("%d", a + i);
50             a[i] = min(a[i], n * 1ll);
51         }
52         BFS();
53         printf("%lld\n", dis[n]);
54     }
55     return 0;
56 }
View Code

 

Problem H. Jhadgre的回家之路

Solved.

两次搜索,搜'L' -> 'W' 和 'Q' -> 'W' 枚举'W'位置更新答案

薛佬交了三发,Rejudge后第一发其实就过

  1 #include<bits/stdc++.h>
  2  
  3 using namespace std;
  4  
  5 const int INF = 0x3f3f3f3f;
  6 const int maxn = 2e3 + 10;
  7  
  8 int n, m;
  9 int vis[maxn][maxn];
 10 int dis1[maxn][maxn];
 11 int dis2[maxn][maxn];
 12 char mp[maxn][maxn];
 13 int dir[4][2] = {1, 0, 0 ,1 ,-1, 0 ,0, -1};
 14  
 15 struct node{
 16     int x, y;
 17     node(){}
 18     node(int x,int y):x(x), y(y){};
 19 }Q,L;
 20  
 21 bool check(int x, int y)
 22 {
 23     if(x < 1 || x > n || y < 1 || y > m || mp[x][y] == '#' || vis[x][y]) return false;
 24     else return true;
 25 }
 26  
 27 vector<node>W;
 28  
 29 void BFS1()
 30 {
 31     memset(vis, 0, sizeof vis);
 32     memset(dis1, INF, sizeof dis1);
 33     vis[L.x][L.y] = 1;
 34     dis1[L.x][L.y] = 0;
 35     queue<node>q;
 36     q.push(L);
 37     while(!q.empty())
 38     {
 39         node st = q.front();
 40         q.pop();
 41         for(int i = 0 ; i< 4; ++i)
 42         {
 43             node now;
 44             now.x = st.x + dir[i][0];
 45             now.y = st.y + dir[i][1];
 46             if(check(now.x, now.y))
 47             {
 48                 vis[now.x][now.y] = 1;
 49                 dis1[now.x][now.y] = dis1[st.x][st.y] + 1;
 50                 q.push(now);
 51             }
 52         }
 53     }
 54 }
 55  
 56 void BFS2()
 57 {
 58     memset(vis, 0, sizeof vis);
 59     memset(dis2, INF, sizeof dis2);
 60     vis[L.x][L.y] = 1;
 61     dis2[Q.x][Q.y] = 0;
 62     queue<node>q;
 63     q.push(Q);
 64     while(!q.empty())
 65     {
 66         node st = q.front();
 67         q.pop();
 68         for(int i = 0 ; i< 4; ++i)
 69         {
 70             node now;
 71             now.x = st.x + dir[i][0];
 72             now.y = st.y + dir[i][1];
 73             if(check(now.x, now.y))
 74             {
 75                 vis[now.x][now.y] = 1;
 76                 dis2[now.x][now.y] = dis2[st.x][st.y] + 1;
 77                 q.push(now);
 78             }
 79         }
 80     }
 81 }
 82  
 83 int main()
 84 {
 85     while(~scanf("%d %d", &n, &m))
 86     {
 87         for(int i = 1; i <= n; ++i)
 88         {
 89             for(int j = 1; j <= m; ++j)
 90             {
 91                 scanf(" %c", &mp[i][j]);
 92                 if(mp[i][j] == 'Q')
 93                 {
 94                     Q = node(i, j);
 95                 }
 96                 else if(mp[i][j] == 'L')
 97                 {
 98                     L = node(i, j);
 99                 }
100                 else if(mp[i][j] == 'W')
101                 {
102                     W.push_back(node(i, j));
103                 }
104             }
105         }
106         BFS1();
107         BFS2();
108         int ans = INF;
109         for(auto it: W)
110         {
111             ans = min(dis1[it.x][it.y] + dis2[it.x][it.y], ans);
112         }
113         printf("%d\n", ans);
114     }
115     return 0;
116 }
View Code

 

Problem I. Jhadgre的小饼干

string.find()

 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 int n;
 6 string s;
 7  
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin.tie(0);
12     cout.tie(0);
13     while(cin >> n)
14     {
15         int sum  = 0;
16         for(int i = 1; i <= n; ++i)
17         {
18             cin >> s;
19             if(s.find("zailaiyihe") != s.npos) sum++;
20         }
21         printf("%d\n", sum);
22     }
23     return 0;
24 }
View Code

 

Problem J. Jhadgre爬楼梯

线性推

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define ll long long
 5 #define N 10010
 6 const ll MOD = (ll)100000007;
 7 int n;
 8 ll f[N], sum[2];
 9  
10 int main()
11 {
12     f[0] = 1;
13     sum[0] = 1, sum[1] = 0;
14     for (int i = 1; i <= 10000; ++i)
15     {
16         f[i] = f[i - 1];
17         f[i] = (f[i] + sum[i & 1]) % MOD;
18         sum[i & 1] = (sum[i & 1] + f[i]) % MOD;
19     }  
20     while (scanf("%d", &n) != EOF) printf("%lld\n", f[n]);
21     return 0;
22 }
View Code

 

Problem L. Wpremig's Niuniu

题意:

规则:

五张牌均严格小于5,五张牌的和小于等于10,得60分。

五张牌都是$J,Q,K$,得50分。

五张牌有四张牌相同,得40分。

如果其中三张牌的和是10的倍数,并且其他两张牌的和是10的倍数,得30分

如果其中三张牌的和是10的倍数,并且其他两张牌的和对于10的余数大于等于7,得$2*$其他两张牌的和对于10的余数

如果其中三张牌的和是10的倍数,并且其他两张牌的和对于10的余数大于等于7,得其他两张牌的和对于10的余数

 其余情况不得分,同时每次只能获取最高分。

现在你手上已经有四张牌,求拿到第五张牌后的分数期望(四舍五入)

思路:

预处理出所有情况,最后遍历一次得到总分后除以13

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
const ll MOD = 1e9 + 7;
 
int ans[20][20][20][20][20];
 
void Init()
{
    for (int a = 1; a <= 13; ++a)
    {
        for (int b = 1; b <= 13; ++b)
        {
            for (int c = 1; c <= 13; ++c)
            {
                for (int d = 1; d <= 13; ++d)
                {
                    for (int e = 1; e <= 13; ++e)
                    {
                        if (a < 5 && b < 5 && c < 5 && d < 5 && e < 5 && a + b + c + d + e <= 10)
                        {
                            ans[a][b][c][d][e] = 60;
                        }
                        else if (a >= 11 && b >= 11 && c >= 11 && d >= 11 && e >= 11)
                        {
                            ans[a][b][c][d][e] = 50;
                        }
                        else if ((a == b && b == c && c == d) || (a == b && b == c && c == e) || (a == b && b == d && d == e) || (a == c && c == d && d == e) || (b == c && c == d && d == e))
                        {
                            ans[a][b][c][d][e] = 40;
                        }
                        else
                        {
                            if ((min(10, a) + min(10, b) + min(10, c)) % 10 == 0 || (min(10, a) + min(10, b) + min(10, d)) % 10 == 0 || (min(10, a) + min(10, b) + min(10, e)) % 10 == 0 || (min(10, a) + min(10, c) + min(10, d)) % 10 == 0 || (min(10, a) + min(10, c) + min(10, e)) % 10 == 0 || (min(10, a) + min(10, d) + min(10, e)) % 10 == 0
                                || (min(10, b) + min(10, c) + min(10, d)) % 10 == 0 || (min(10, b) + min(10, c) + min(10, e)) % 10 == 0 || (min(10, b) + min(10, d) + min(10, e)) % 10 == 0 || (min(10, b) + min(10, d) + min(10, e)) % 10 == 0
                                || (min(10, c) + min(10, d) + min(10, e)) % 10 == 0)
                            {
                                int sum = min(10, a) + min(10, b) + min(10, c) + min(10, d) + min(10, e);
                                if (sum % 10 == 0) ans[a][b][c][d][e] = 30;
                                else if (sum % 10 >= 7) ans[a][b][c][d][e] = 2 * (sum % 10);
                                else ans[a][b][c][d][e] = sum % 10;
                            }
                        }
                    }
                }
            }
        }
    }
}
 
void RUN()
{
    Init();
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int a, b, c, d;
        scanf("%d %d %d %d", &a, &b, &c, &d);
        int sum = 0;
        for (int i = 1; i <= 13; ++i) sum += ans[a][b][c][d][i];
        sum = (sum / 13.0) + 0.5;
        printf("%d\n", sum);
    }
}
 
int main()
{
#ifdef LOCAL_JUDGE
    freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
 
    RUN();
 
#ifdef LOCAL_JUDGE
    fclose(stdin);
#endif // LOCAL_JUDGE
    return 0;
}
View Code

枚举最后一张牌,求总分,最后除以13

#include<bits/stdc++.h>
 
using namespace std;
 
int a[10], b[10];
int c[15];
 
void RUN()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        for (int i = 1; i <= 4; ++i) scanf("%d", a + i);
        b[1] = min(10, a[1]) + min(10, a[2]);
        b[2] = min(10, a[1]) + min(10, a[3]);
        b[3] = min(10, a[1]) + min(10, a[4]);
        b[4] = min(10, a[2]) + min(10, a[3]);
        b[5] = min(10, a[2]) + min(10, a[4]);
        b[6] = min(10, a[3]) + min(10, a[4]);
        b[7] = 0;
        int tmp = 0;
        for (int i = 1; i <= 4; ++i) tmp += min(10, a[i]);
        for (int i = 1; i <= 4; ++i)
        {
            if ((tmp - min(10, a[i])) % 10 == 0)
            {
                b[7] = 1;
                break;
            }
        }
 
        double ans = 0;
        for (int i = 1; i <= 13; ++i)
        {
            a[5] = i;
            //1
            if (a[1] < 5 && a[2] < 5 && a[3] < 5 && a[4] < 5 && a[5] < 5 && a[1] + a[2] + a[3] + a[4] + a[5] <= 10)
            {
                ans += 60.0;
                continue;
            }
 
            //2
            if (a[1] >= 11 && a[2] >= 11 && a[3] >= 11 && a[4] >= 11 && a[5] >= 11)
            {
                ans += 50.0;
                continue;
            }
 
            //3
            if ((a[1] == a[2] && a[2] == a[3] && a[3] == a[4]) || (a[1] == a[2] && a[2] == a[3] && a[3] == a[5]) || (a[1] == a[2] && a[2] == a[4] && a[4] == a[5]) || (a[1] == a[3] && a[3] == a[4] && a[4] == a[5]) || (a[2] == a[3] && a[3] == a[4] && a[4] == a[5]))
            {
                ans += 40.0;
                continue;
            }
 
            //4
            int sum = 0;
            for (int i = 1; i <= 5; ++i) sum += min(10, a[i]);
            if (b[7])
            {
                if (sum % 10 == 0) ans += 30.0;
                else if (sum % 10 >= 7) ans += 2.0 * (sum % 10);
                else ans += sum % 10;
                continue;
            }
            //5
            int res = -1;
            for (int j = 1; j <= 6; ++j)
            {
                if ((b[j] + min(10, a[5])) % 10 == 0)
                {
                    res = sum % 10;
                    break;
                }
            }
            if (res == -1) continue;
            if (res == 0) ans += 30.0;
            else if (res >= 7) ans += 2.0 * res;
            else if (res != -1) ans += res;
        }
        ans = (ans / 13.0) + 0.5;
        printf("%d\n", (int)ans);
    }
 
}
 
int main()
{
#ifdef LOCAL_JUDGE
    freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
 
    RUN();
 
#ifdef LOCAL_JUDGE
    fclose(stdin);
#endif // LOCAL_JUDGE
    return 0;
}
View Code

比赛的时候写丑了,同时对于题意理解不明确?(说好的一副牌呢!)

posted @ 2018-12-23 10:30  Dup4  阅读(314)  评论(0编辑  收藏  举报