• ZZULI-周赛5题解


    其实比赛我们三都觉得出的没问题的,但还是出锅了,不止是难度不对口,而且比赛期间A题数据出错了,一直在改数据,到最后才改完。。。

    先向各位新生同学说声抱歉吧,没给你们好的周赛体验.如果再来一次,肯定还给你们搞成这样,应该会好好出点有梯度的题目.

    本次出题人实力有限,望各位大佬踊跃提出问题和指导,狗头.

    A:

      题型:水题(出题人原话

      思路:小模拟小模拟...就需要注意一下闰年还是非闰年...亿点点小细节

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define debug(x) cout << #x << "=" << x << endl
    #define debug2(x, y) cout << #x << "=" << x << "," << #y << "=" << y << endl
    //   *(ve._M_impl._M_start)@(ve.size())
    char *p[] = {"NO", "YES"};
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 7;
    ll day_run[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    ll day_pin[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    ll pan(ll y)
    {
        if (y % 4 == 0 && y % 100 != 0)
        {
            return 1;
        }
        else if (y % 400 == 0)
        {
            return 1;
        }
        return 0;
    }
    void add(ll &y, ll &m, ll &d)
    {
        d++;
        if (pan(y))
        {
            if (day_run[m] < d)
            {
                m++;
                d = 1;
            }
            if (m > 12)
            {
                y++;
                m = 1;
            }
        }
        else
        {
            if (day_pin[m] < d)
            {
                m++;
                d = 1;
            }
            if (m > 12)
            {
                y++;
                m = 1;
            }
        }
    }
    ll hanyou(ll &y, ll &m, ll &d, ll &y2, ll &m2, ll &d2)
    {
        ll s = y * 10000 + m * 100 + d;
        ll s2 = y2 * 10000 + m2 * 100 + d2;
        if (s <= s2)
        {
            return 1;
        }
        return 0;
    }
    int main()
    {
        ll y, m, d, n, i, a, b, c, sh = 14, lo = 66;
        ll ys, ms, ds, yl, ml, dl;
        scanf("%lld-%lld-%lld", &y, &m, &d);
        ys = yl = y;
        ms = ml = m;
        ds = dl = d;
        for (i = 1; i < sh; i++)
        {
            add(ys, ms, ds);
        }
        for (i = 1; i < lo; i++)
        {
            add(yl, ml, dl);
        }
        scanf("%lld", &n);
        for (i = 0; i < n; i++)
        {
            scanf("%lld-%lld-%lld", &a, &b, &c);
            if (hanyou(a, b, c, ys, ms, ds))
            {
                add(ys, ms, ds);
            }
            if (hanyou(a, b, c, yl, ml, dl))
            {
                add(yl, ml, dl);
            }
        }
        printf("%lld-%lld-%lld
    ", ys, ms, ds);
        printf("%lld-%lld-%lld
    ", yl, ml, dl);
        return 0;
    }

    B:略

    C: 

      题型:思维题...

      思路:对于数组中第 i 个元素考虑计算次数,当前元素只被前 i - 1 个元素乘一遍(记得取余操作,还有long long避免数据溢出).

         前后缀都可以做到.

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 100;
    typedef  long long ll;
    ll a[maxn],sum[maxn];
    const int mod = 1e9 + 7;
    
    int main(){
        int n;cin >> n;
        for(int i = 1;i <= n;i++) {
            cin >> a[i];
            sum[i] = sum[i - 1] + a[i];
            sum[i] %= mod;
        }
        ll ans = 0;
        for(int i = 2;i <= n;i++){
            ans = (ans + a[i] * sum[i-1]) % mod;
        }
        cout << ans % mod<< endl;
        return 0;
    }

    D:

      题型:思维题...(题面可能没解释清楚...我的锅)

      思路:对于 i ( 0 < i <= n) 来说,A[ i ]就是被引用 i 次的文章个数,那么可以考虑从 i = n 循环到i == 0.维护当前 i ~ n 之间的和 sum,当满足 sum >= i 就是题目要求的答案,输出当前 i 即可.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5 + 100;
    
    int n, a[maxn];
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n + 1; i++)
            scanf("%d", &a[i]);
        ll sum = a[n + 1];
        for (int i = n; i >= 0; i--)
        {
            if (sum >= i)
            {
                printf("%d
    ", i);
                break;
            }
            sum += a[i];
        }
        return 0;
    }

    E:

      题型:数学知识...

      思路:

        设 x <= y,当 x == y 时,原式出成立,所以x < y。

        因为x < y + GCD ( x , y )  <  y,所以 x + y + GCD ( x , y )  <  3y,又因为 x + y + GCD ( x , y )  > y 且 LCM ( x , y ) 是 y 的整数倍,所以 x < y + GCD ( x , y )  = 2y,且 LCM ( x , y ) = 2y。

        因为 x * y =GCD ( x , y ) * LCM ( x , y ) ,所以 x * y = 2y * GCD ( x , y ),得到 GCD ( x , y ) = x / 2;带回原式得 x + y + x / 2 = 2y,解得 x  = 2 / 3y或者 y = 3/2x。

        由以上结论得,对于每个偶数x,满足 x + y +GCD ( x , y ) = LCM ( x , y ) 且大于 x 的 y 有且只有一个,即 y = 3 / 2x。而奇数则不存在这样的y。

        所以将选出来的数从小到大排序,去重,一定满足 bi  =  2 / 3b( i + 1) (1 <= i <= k)。

    #include<stdio.h>
    #include<math.h>
    #include<stdlib.h>
    #define N 200000
    int n,a[N],ans = -1,b[N];
    int main(void){
        scanf("%d",&n);
        for(int i = 0;i<n;i++){
            scanf("%d",&a[i]);
            b[a[i]]++;   //通过 b 数组来统计 a[i]的个数
        }
        for(int i = 0;i < n;i++){      //冒泡排序
            for(int j = 0;j <n-1-i;j++){
                if(a[j]>a[j+1]){
                    int temp = a[j];
                    a[j] =a[j+1];
                    a[j+1] =temp;
                }
            }
        }

        for(int i = 0;i<n;i++){
            int temp = a[i],sum = 0;
            while(b[temp]){   //从数组中取出一个数,然后在 while 训中改变数值;
                sum +=temp*b[temp];   //当该数存在时,进行循环,sum 统计存在的值,该值要 乘上其个数
                if(temp%2==0)     //更加推论,如果该数是偶数,则寻找对应的 y 值,
                temp = temp/2*3;
                else
                break;
            }
            if(sum>ans)    //获得最大的累加之积
            ans =sum;
        }
        printf("%d ",ans);
        return 0;
    }

    F:

      题型:模拟...

      思路:直接模拟接水过程,刚开始时让m个水龙头都开着,m个同学都在接水,一旦有一个同学接完了,下一个同学就立刻来这个水龙头接水。

    #include<stdio.h>
    #include<math.h>
    #include<stdlib.h>
    #define N 200000
    int a[N],b[N],n,m,t,ans;
    int main(void){
        scanf("%d %d",&n,&m);
        for(int i = 1;i<=n;i++)
        scanf("%d",&a[i]);
        t = m + 1;  //记录等待接水的队伍中的第一个学生的编号
        while(t<=n+m){
            for(int i = 1;i<=m;i++){    //枚举m个水龙头,在一次循环结束后,
    //接水的m个同学的要接的水的量减一
                a[i]--;          
                if(!a[i]){               //如果有个同学接完水了,下一个同学补上
                    a[i] =a[t];
                    t++;            
                }
            
            }
            ans++;                //当for循环结束后,表示模拟的时间为1秒,ans加一
        } 
        printf("%d
    ",ans);
        return 0;
    } 

    G:

      题型:模拟...

      思路:直接根据题意模拟,标记小K学长和女神吃到第几个糖果,以及他们所用的时间,如果女神当前的时间小于等于小K学长的时间,则女神开始吃下一个,否则小K学长开始吃下一个。

    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #define N 100000
    int n, a[N], l, r, sum1, sum2;
    
    int main(void)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        l = 1, r = n; //l代表女神吃到糖果的位置,r代表小K迟到的糖果的位置
        while (l <= r)
        {
            if (sum1 <= sum2)
            { //sum1代表女神所用的时间,sum2代表小K学长所用的时间, sum1 +=a[l++];          //如果sum1<=sum2,则女神开始吃下一个糖果
                sum1 += a[l++];
            }
            else
            {
                sum2 += a[r--];
            }
        }
        printf("%d %d", l - 1, n - l + 1); //l-1表示女神吃到的糖果的位置,因为女神是从前往后开始  //吃的,所以l-1也表示女神吃了几个,那么剩下的就代表小K学长吃的糖果数。
        return 0;
    }

    H:

      题型:大模拟(手动狗头

      思路:直接模拟呀!!!(来自队友大佬的原话

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    char *p[] = {"NO", "YES"};
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 7;
    ll jiafen(ll liansheng, ll jili[])
    {
        if (liansheng > 5)
        {
            liansheng = 5;
        }
        return jili[liansheng];
    }
    char *pqwe[] = {"", "Bronze", "Silver", "Gold", "Platinum", "Diamond", "Star", "the strongest king"};
    int main()
    {
        char a[2000];
        while (~scanf("%s", a))
        {
            ll liststar[] = {0, 3, 3, 4, 4, 5, 5, 200};
            ll listduan[] = {0, 3, 3, 4, 5, 5, 5, 1};
            ll jili[] = {0, 0, 8, 13, 18, 23};
            ll le = 1, le2 = 1, star = 0, i, len, integral = 0, card = 0;
            ll jifenwin = 10, liansheng;
    
            len = strlen(a);
            liansheng = 0;
            for (i = 0; i < len; i++)
            {
                if (a[i] == 'W')
                {
                    liansheng++;
                    star++;
                    integral += jifenwin;
                    integral += jiafen(liansheng, jili);
                    if (integral >= 350)
                    {
                        integral -= 350;
                        star++;
                    }
                    if (star > liststar[le])
                    {
                        star -= liststar[le];
                        le2++;
                        if (le2 > listduan[le])
                        {
                            le2 -= listduan[le];
                            le++;
                            card += 2;
                        }
                    }
                }
                else
                {
                    liansheng = 0;
                    if (le == 1)
                    {
                        continue;
                    }
                    else if (le == 2 && le2 == 1 && star == 0)
                    {
                        continue;
                    }
                    if (card)
                    {
                        card--;
                    }
                    else if (integral >= 150)
                    {
                        integral = 0;
                    }
                    else
                    {
                        star--;
                        if (star < 0)
                        {
                            le2--;
                            if (le2 < 1)
                            {
                                le--;
                                le2 = listduan[le];
                            }
                            star = liststar[le] - 1;
                        }
                    }
                }
            }
            if (le != 7)
                printf("%s-%lld-%lld
    ", pqwe[le], le2, star);
            else
                printf("%s-%lld
    ", pqwe[le], star);
        }
        return 0;
    }

    I:

      题型:DP...(想当防AK题的

      思路:对于第二个答案,就是数组中最长上升子序列的长度,因为对于第 i 个元素,如果没有比前 i - 1 个元素小,那么必然需要再多一个导弹系统来放出更高的防空导弹来防卫,即就数组中最长上升子序列的长度.

            对于第一个答案,就是反向数组最长非下降子序列的长度 .

           哈?你问我什么事最长上升子序列?建议百度,我太菜了...

    // 输入可以使用简单的 while(scanf("%d",&a[i]) != EOF) 
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    
    int dp[100005];
    int main(){
        string s;getline(cin,s);
        stringstream ss;
        ss << s;
        vector<int> q;
        int x;
        while(ss >> x) q.push_back(x);
       // 输入可以使用简单的 while(scanf("%d",&a[i]) != EOF)
    int n = q.size(); for(int i = 0;i <= n;i++) dp[i] = inf; for(int i = 0;i < q.size();i++){ *lower_bound(dp,dp+n,q[i]) = q[i]; } int cnt = lower_bound(dp,dp+n,inf) - dp; reverse(q.begin(),q.end()); for(int i = 0;i <= n;i++) dp[i] = inf; for(int i = 0;i < q.size();i++){ *upper_bound(dp,dp+n,q[i]) = q[i]; } cout << lower_bound(dp,dp+n,inf) - dp << endl; cout << cnt <<endl; return 0; }
  • 相关阅读:
    self 和 super 关键字
    NSString类
    函数和对象方法的区别
    求两个数是否互质及最大公约数
    TJU Problem 1644 Reverse Text
    TJU Problem 2520 Quicksum
    TJU Problem 2101 Bullseye
    TJU Problem 2548 Celebrity jeopardy
    poj 2586 Y2K Accounting Bug
    poj 2109 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/Wise-XiaoWei4/p/14057838.html
Copyright © 2020-2023  润新知