• 2019牛客多校第一场


    2019牛客多校第一场

    A:Equivalent Prefixes(单调栈)

    • 题意:注意是每个子区间都要满足
    • 可以发现必须要有单调性,想到要同增同减
    • 然后找到一个满足同增同减,但是不符合题意的反例:
      • 1 3 2
      • 1 3 0
    • 然后发现必须要维护一个以当前点结尾的最长上升子序列长度相同
    • 如果不同就break
    • 就想到单调栈 不过我不会严格证明,比赛的时候找不到反例
    #include <bits/stdc++.h>
    
    #define ll long long
    using namespace std;
    const ll mod = 1e9 + 7;
    const int N = 1e5 + 10;
    int a[N], b[N];
    int q1[N], q2[N];
    
    int main() {
        int n;
        while (scanf("%d", &n) != EOF) {
            for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
            for (int i = 1; i <= n; i++)scanf("%d", &b[i]);
            int l1 = 0, r1 = 0, l2 = 0, r2 = 0;
            int ans = 1;
            for (int i = 1; i <= n; i++) {
                while (l1 <= r1 && q1[r1] > a[i]) {
                    r1--;
                }
                q1[++r1] = a[i];
                while (l2 <= r2 && q2[r2] > b[i]) {
                    r2--;
                }
                q2[++r2] = b[i];
                if ((r1 - l1) == (r2 - l2))ans = i;
                else break;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    

    B: Integration(数学)

    • 题意:求那个积分
    • 裂项
      • 把乘换成减,两项两项地换
      • 复杂度(O(n^2))
      • 积分的可加性
      • (pre)记录系数,最后再乘以积分的值(pi/{2a})
    • 代码
    #include <bits/stdc++.h>
     
    #define ll long long
    using namespace std;
    const int mod = 1e9 + 7;
    ll s[1010];
    ll pre[1010];
     
    ll qpow(ll a, ll n) {
        ll res = 1;
        a %= mod;
        while (n) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }
     
    int main() {
        int n;
        while (scanf("%d", &n) != EOF) {
            for (int i = 1; i <= n; ++i) scanf("%lld", &s[i]), pre[i] = 0;
            pre[1] = 1;
            for (int i = 2; i <= n; ++i) {
                for (int j = 1; j < i; ++j) {
                    pre[j] = (pre[j] * qpow(((s[i] * s[i] % mod - s[j] * s[j] % mod)%mod + mod) % mod,mod-2)+mod)% mod;
                    pre[i] = ((pre[i] - pre[j]) % mod + mod) % mod;
                }
            }
            ll ans = 0;
            for (int i = 1; i <= n; ++i) {
                ans = ((ans + pre[i] * qpow(s[i] * 2LL, mod - 2) % mod+mod)%mod+mod) % mod;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    C:Euclidean Distance(数学+贪心)

    #include <bits/stdc++.h>
    
    #define ll long long
    using namespace std;
    const int mod = 1e9 + 7;
    const int maxn = 1e4 + 10;
    ll s[maxn];
    ll pre[maxn];
    
    int main() {
        int n, m;
        while (scanf("%d%d", &n, &m) != EOF) {
            for (int i = 1; i <= n; ++i) {
                scanf("%lld", &s[i]);
            }
            sort(s + 1, s + 1 + n);
            reverse(s + 1, s + 1 + n);
            pre[0] = -m;
            for (int i = 1; i <= n; ++i) {
                pre[i] = pre[i - 1] + s[i];
            }
            ll pos = n;
            for (ll i = 0; i < n; ++i) {
                if (pre[i] > s[i + 1] * i) {
                    pos = i;
                    break;
                }
            }
            ll ansa = pre[pos] * pre[pos] * pos;
            ll ansb = pos * pos;
            for (ll i = pos + 1; i <= n; ++i) {
                ansa += s[i] * s[i] * ansb;
            }
            ansb *= (m * m);
            ll g = __gcd(ansa, ansb);
            ansa /= g;
            ansb /= g;
            if (ansb == 1) {
                printf("%lld
    ", ansa);
            } else {
                printf("%lld/%lld
    ", ansa, ansb);
            }
        }
        return 0;
    }
    

    E:ABBA(贪心+DP)

    • 题意:就是有(n)个"AB",(m)个"BA",问能结合成多少个序列.这个要求是AB和BA的顺序不变,即A和B的相对位置不变.我们要讨论一下什么才是合法的状态.

    • 贪心:

      • 假设只有(n​)个AB,合法情况是每个B前面要有(1 ...n​)个A
      • 假设除了有AB,还有(m)个BA,那每个B前面可以有超过(n)个A,但是第一个B前面还是要有(1...n)个A.否则就会使BA类型的某个B后面没A.
      • B与后面的A可以构成BA,相当于抵消了一个A,那下一个B前面就只需要有(1...n​)未被抵消的A.
      • 所以A-B小于等于(n)是合法的.当A-B等于(n),意味着最后一个只能是A,因为如果最后一个是B,那B前面就有(n+1)个未被抵消的A.
      • A前面有多少个B也是同理.
    • DP

      • (dp[i][j])(i)代表A的个数,(j)代表B的个数.(dp)值代表合法方案.

      • 初始化,按照上述前缀的限定

      • (dp[i][0]=dp[0][j]=1)

      • 不考虑那么多,可以简单得出

        [dp[i][j]=dp[i-1][j]+dp[i][j-1] ]

      • 但是要排除非法的情况

        • (0leq j-ileq m)(0leq i-j leq n) 是合法情况
        • 注意(=m)(=n)(=0)的情况
    • 代码

      #include <bits/stdc++.h>
      
      #define ll long long
      using namespace std;
      const ll mod = 1e9 + 7;
      const ll N = 1e5 + 10;
      ll dp[2010][2010];
      
      int main() {
          ll n, m;
          while (scanf("%lld%lld", &n, &m) != EOF) {
              ll cnt = (n + m);
              for (int i = 0; i <= cnt; i++)
                  for (int j = 0; j <= cnt; j++)
                      dp[i][j] = 0;
              for (ll i = 0; i <= cnt; i++) {
                  dp[i][0] = dp[0][i] = 1;
              }
              for (ll i = 1; i <= cnt; i++) {
                  for (ll j = 1; j <= cnt; j++) {
                      if (i == j) {
                          if (n)
                              dp[i][j] = (dp[i][j] + dp[i][j - 1]) % mod;
                          if (m)
                              dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
                      } else if (j > i) {
                          if (j - i < m)
                              dp[i][j] = ((dp[i][j] + dp[i - 1][j]) % mod + dp[i][j - 1]) % mod;
                          else if (j - i == m)
                              dp[i][j] = (dp[i][j] + dp[i][j - 1]) % mod;
                      } else if (i > j) {
                          if (i - j < n)
                              dp[i][j] = ((dp[i][j] + dp[i - 1][j]) % mod + dp[i][j - 1]) % mod;
                          if (i - j == n)
                              dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
                      }
                      //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
                  }
              }
              printf("%lld
    ", dp[cnt][cnt] % mod);
          }
      
          return 0;
      
    

    F:Random Point in Triangle(期望+随机+叉积)

    参考了一下大牛的博客

    https://www.cnblogs.com/WAautomaton/p/11211864.html

    首先我们得出当一个点P随机落在三角形内部,新三角形BPC的高的期望为(H/3)
    证明如下:(字丑勿怪)
    图片说明
    得到了这个,那就好办了,就变成了简单几何问题.
    剩下的可以看大佬的博客,我就不赘述了.

    #include <bits/stdc++.h>
    
    #define ll long long
    using namespace std;
    const ll mod = 1e9 + 7;
    const ll N = 1e5 + 10;
    
    int main() {
        ll x1, y1, x2, y2, x3, y3;
        while (~scanf("%lld%lld%lld%lld%lld%lld", &x1, &y1, &x2, &y2, &x3, &y3)) {
            ll ans = 11;
            ll cnt = abs(x1 * y2 + x2 * y3 + x3 * y1 - x1 * y3 - x2 * y1 - x3 * y2);
            ans = ans * cnt;
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    Fraction Comparision(大数+JAVA)

    居然不会JAVA的多组输入,JAVA白考98了…..

    一开始用了nextline 一直RE.

    import java.math.*;
    import java.util.*;
    public class Main {
        static BigInteger ans,m;
        static BigInteger[] arr;
        static int n;
        public static void main(String []args){
      
          Scanner cin = new Scanner(System.in);
          //Long x,a,y,b;
          BigInteger x,a,y,b;
          while(cin.hasNextBigInteger()){
              x=cin.nextBigInteger();
              a=cin.nextBigInteger();
              y=cin.nextBigInteger();
              b=cin.nextBigInteger();
              int s=b.multiply(x).compareTo(a.multiply(y));
              if(s>0){
                  System.out.println(">");
              }else if(s==0){
                  System.out.println("=");
              }else{
                  System.out.println("<");
              }
          }
        }
      
    }
    
    不要忘记努力,不要辜负自己 欢迎指正 QQ:1468580561
  • 相关阅读:
    STDMETHOD (转)
    DirectX中的纹理映射相关技术 (转)
    (转)清空std::stringstream,联系到stream的clear()和清空
    (转载)MultiAnimation
    (转)SkyBox
    [转载]漫谈游戏中的阴影技术
    反射矩阵计算
    (转)COM组件里的AddRef()
    LINQ简记(2):重要概念
    继续聊WPF——自定义命令
  • 原文地址:https://www.cnblogs.com/smallocean/p/11209720.html
Copyright © 2020-2023  润新知