zoukankan      html  css  js  c++  java
  • 8.15早训有意思的题

    B - Mister B and Angle in Polygon

     CodeForces - 820B 

    计算几何

    题意

    输入n个点,创建一个正n边形,把每个点之间都连起来(如下图举例所示),求出最接近所给∠a的角的角的三个顶点a,b,c,其中b为顶点。

    题解

    先说下这题的思路,这题并不是难在代码,但是不太好想。正n边形的内角和为 (n-2)*180°,这个公式当时自然记得。
    但是,有些别的点却是要自己想的,简述思路如下:
    正n边形每个顶角的大小为 (n-2)*180/n°
    对正n边形的任一顶点,除去它自己和相邻的两个顶点,该定顶点可以与剩余的 (n-3) 个顶点连成(n-3)条对角线,这些对角线可将该顶点对应的顶角分为(n-3)+1,即(n-2)个部分,每部分180/n°
    
    于是正n边形任意三个顶点构成的角度的范围,则是从 180/n° ~ 180 * (n-2) /n°
    为了方便输出,许多博客上的题解,都是采用固定前两个顶点,例如固定2 1,因为这样固定,目标答案所对应的角度,和第三个顶点的序号的的关系,比较容易能表示出来
    
    #include <bits/stdc++.h>
    using namespace std;
    int main(int argc, char const *argv[])
    {
        int n , a;
        cin >> n >> a;
        double tmp = 180.0 * (n - 2) / n ;
        double ang = (180.0 - tmp) / 2;
        double angs = ang;
        int id = 3; 
        for(int i = 4;i <= n;i ++){
            double ans = 1.0 * ang * (i - 2);
            if(abs(angs - a) > abs(ans - a)){
                angs = ans;
                id = i;
            }
        }
        cout << "2 1 " << id <<endl;
        return 0;
    }

    C - Mister B and PR Shifts

     CodeForces - 820D 

    用cnt数组记录当前num[i]所在位置 到 下标为num[i]的位置 需要向右循环移位几次,两个变量add、sub表示下一次移位会使sum值+1/-1的个数,每次更新均在上一排列的基础上进行。

    先注意题意, 1 <= num[i] <= n。

    再注意一点,对于每个位置的数,设为num[i],先不看num[i] = 0或者num[i] = n的情况,对于其他情况,从1到num[i]这段区间,num[i]右移使|num[i] - loc|单减,从num[i]到n这段区间,num[i]右移使|num[i] - loc|单增;对于num[i] = 0,从1到n,|num[i] - loc|一直单增;对于num[i] = n,num[i]右移使|num[i] - loc|单减;当num[i]从n移动到1,增减不一定。所以对于每个数num[i],位置num[i]是个转折点,决定下一步|num[i] - loc|如何变化(每次+1还是-1)。具体思路见注释。

    // CodeForces 820D Mister B and PR Shifts 运行/限制:264ms/2000ms
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LL long long
    int num[1000005],cnt[1000005];
    int main(){
        int n;
        int add, sub, index;
        LL sum, re;
        while (scanf("%d", &n) != EOF) {
            sum = 0; add = 0; sub = 0;
            memset(cnt, 0, sizeof(cnt));
            for (int i = 1; i <= n; i++) {
                scanf("%d", &num[i]);
                sum += fabs(num[i] - i);
                cnt[(num[i] - i + n) % n]++;//cnt下标为:当前num[i]所在位置 到 num[i]位置 需要移位几次
                if (num[i] > i) sub++;//下一次移位会使值-1的个数
                else add++;//下一次移位会使值+1的个数
            }
            re = sum; index = 0;
            for (int i = 1; i < n; i++) {//每次在前一次移位的基础上处理,i为第几次移动
                sum += add - sub - 1;//当前最后一位肯定满足数值小于等于n(数据范围最大是n),所以之前计算在add里了;但因为要移动到首位,所以不一定是加、减
                sum += (num[n - i + 1] - 1) - (n - num[n - i + 1]);//计算当前最后一位移动到首位sum值的变化;
                                                                   //每次并没有真正进行移位,而是每次计算最后一位应该是未移位序列的哪个位置了
     
                //求完sum,相当于该次移动了
     
                //根据此次移动后的结果,更新下一步add、sub会出现的值
                //-1,+1是因为这一次移动后到第一个位置的数,由于单调性反转,使add比正常情况-1、sub+1。
                //num[i] = 1时,|num[i] - loc|全程单调递增,从n位置移动到1位置时单调性的变化是个特例,可以分析一下num[n] = 1也满足下面式子
                add = add + cnt[i] - 1;
                sub = sub - cnt[i] + 1;
                if (sum < re) {
                    re = sum;
                    index = i;
                }
            }
            printf("%lld %d
    ", re, index);
        }
        return 0;
    }

    E - Okabe and Banana Trees

     CodeForces - 821B 

    枚举Y,等差数列求和

    #include <bits/stdc++.h>
    using namespace std;
    int main(int argc, char const *argv[])
    {
        // y = -x/m + b
        long long m , b ;
        cin >> m >> b;
        long long maxx = 0;
        for(int i = b;i >= 0;i --){
            long long sum = 0;
            long long border = m * (b - i);
            sum=((border+1)*border/2)*(i+1)+(i*(i+1)/2)*(border+1);
            if(sum > maxx) maxx = sum;
        }
        cout << maxx << endl;
        return 0;
    }

    F - Okabe and Boxes

     CodeForces - 821C

    思维,vector 模拟一下,点 : 不满足排序 == 清空vector 

    #include <bits/stdc++.h>
    using namespace std;
    std::vector<int> v;
    int main(int argc, char const *argv[])
    {
        int n ;
        cin >> n ;
        int cnt = 0,ans = 0;
        string str;
        while(cin >> str){
            //cnt ++;
            if(str[0] == 'a'){
                int x;cin >> x;
                v.push_back(x);
            }else{
                cnt++;
                if(!v.empty())
                if(v.back() == cnt) v.pop_back();
                else v.clear(),ans++;
            }
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    Delphi XE4 FireMonkey 开发 IOS APP 发布到 AppStore 最后一步.
    Native iOS Control Delphi XE4
    Delphi XE4 iAD Framework 支持.
    using IOS API with Delphi XE4
    GoF23种设计模式之行为型模式之命令模式
    Android青翼蝠王之ContentProvider
    Android白眉鹰王之BroadcastReceiver
    Android倚天剑之Notification之亮剑IOS
    Android紫衫龙王之Activity
    GoF23种设计模式之行为型模式之访问者模式
  • 原文地址:https://www.cnblogs.com/DWVictor/p/11357356.html
Copyright © 2011-2022 走看看