zoukankan      html  css  js  c++  java
  • 2017 JUST Programming Contest 2.0 题解

    题目链接

    A - On The Way to Lucky Plaza

    首先,$n>m$或$k>m$或$k>n$就无解。

    设$p = frac{A}{B}$,$ans = C_{n - 1}^{k - 1}{left( {frac{A}{B}} ight)^{k}}{left( {frac{B-A}{B}} ight)^{n - k}} = frac{{left( {n - 1} ight)! imes {A^k} imes {{left( {B - A} ight)}^{n - k}}}}{{left( {k - 1} ight)! imes left( {n - k} ight)! imes {B^n}}}$。令分子为$p$,分母为$q$,最终的答案为$p$*($q$的逆元)。

    #include <bits/stdc++.h>
    using namespace std;
    
    const long long mod = 1e9 + 7;
    const int maxn = 2e5 + 10;
    long long f[maxn];
    
    long long m, n, k;
    char s[maxn];
    
    long long qpow(long long a, long long b) {
      long long res = 1LL;
      a = a % mod;
      while(b) {
        if(b & 1) res = (res * a) % mod;
        b = b / 2;
        a = (a * a) % mod;
      }
      return res;
    }
    
    long long extend_gcd(long long a,long long b,long long &x,long long &y)
    {
      if(a==0&&b==0) return -1;//无最大公约数
      if(b==0){x=1;y=0;return a;}
      long long d=extend_gcd(b,a%b,y,x);
      y-=a/b*x;
      return d;
    }
    //*********求逆元素*******************
    //ax = 1(mod n)
    long long mod_reverse(long long a,long long n)
    {
      long long x,y;
      long long d=extend_gcd(a,n,x,y);
      if(d==1) return (x%n+n)%n;
      else return -1;
    }
    
    void init() {
      f[0] = 1LL;
      for(long long i = 1; i <= 100000; i ++) {
        f[i] = (f[i - 1] * i) % mod;
      }
    }
    
    int main() {
      init();
      cin >> m >> n >> k >> s;
      if(n > m || k > m || k > n) {
        printf("0
    ");
        return 0;
      }
      if(s[0] == '1' && n == k) {
        printf("1
    ");
        return 0;
      }
      if(s[0] == '1') {
        printf("0
    ");
        return 0;
      }
      if(s[0] == '0' && s[2] == '0' && s[3] == '0' && s[4] == '0') {
        printf("0
    ");
        return 0;
      }
      
      long long A = 0;
      long long B = 1000LL;
      for(int i = 2; i <= 4; i ++) {
        A = A * 10LL + s[i] - '0';
      }
      
      long long p, q;
      
      p = f[n - 1] * qpow(A, k) % mod;
      p = p * qpow(B - A, n - k) % mod;
      
      q = f[k - 1] * f[n - k] % mod;
      q = q * qpow(B, n) % mod;
      
      long long x = p * mod_reverse(q, mod) % mod;
      printf("%lld
    ", x);
      return 0;
    }
    

    B - So You Think You Can Count?

    设$dp[i]$表示以$i$为结尾的方案数,每个位置最多往前扫$10$位。

    #include <bits/stdc++.h>
    using namespace std;
    
    const long long mod = 1e9 + 7;
    const int maxn = 1e5 + 10;
    char s[maxn];
    int n;
    long long dp[maxn];
    
    long long DP(int x) {
      if(x < 0) return 1LL;
      return dp[x];
    }
    
    int main() {
      scanf("%d", &n);
      scanf("%s", s);
      int len = strlen(s);
      dp[0] = 1LL;
      for(int i = 1; i < len; i ++) {
        int tmp[20];
        for(int j = 0; j <= 9; j ++) {
          tmp[j] = 0;
        }
        for(int pre = i; pre >= 0; pre --) {
          if(tmp[s[pre] - '0']) break;
          tmp[s[pre] - '0'] = 1;
          dp[i] = (dp[i] + DP(pre - 1)) % mod;
        }
      }
      printf("%lld
    ", dp[len - 1]);
      return 0;
    }
    

    C - MRT Map

    最短路,数据有点水,没把spfa卡住。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5 + 10;
    
    int S, T, n, m;
    char name[maxn][25];
    int h[maxn], nx[maxn], to[maxn], c[maxn], sz;
    int t1[30], t2[30];
    
    int cost(int x, int y) {
      memset(t1, 0, sizeof t1);
      memset(t2, 0, sizeof t2);
      
      for(int i = 0; name[x][i]; i ++){
        if(name[x][i] >= 'a' && name[x][i] <= 'z') {
          t1[name[x][i] - 'a'] ++;
        }
        if(name[x][i] >= 'A' && name[x][i] <= 'Z') {
          t1[name[x][i] - 'A'] ++;
        }
      }
      
      for(int i = 0; name[y][i]; i ++){
        if(name[y][i] >= 'a' && name[y][i] <= 'z') {
          t2[name[y][i] - 'a'] ++;
        }
        if(name[y][i] >= 'A' && name[y][i] <= 'Z') {
          t2[name[y][i] - 'A'] ++;
        }
      }
      
      int num = 0;
      for(int i = 0; i < 26; i ++) {
        if(t1[i] && t2[i]) num ++;
      }
      return num;
    }
    
    void add(int x, int y, int z) {
      to[sz] = y;
      c[sz] = z;
      nx[sz] = h[x];
      h[x] = sz++;
    }
    
    int dis[maxn], f[maxn];
    
    void spfa() {
      for(int i = 1 ;i <= n; i ++) {
        f[i] = 0;
        dis[i] = 0x7FFFFFFF;
      }
      queue<int> Q;
      Q.push(S);
      f[S] = 1;
      dis[S] = 0;
      while(!Q.empty()) {
        int top = Q.front();
        Q.pop();
        f[top] = 0;
        for(int i = h[top]; i != -1; i = nx[i]) {
          if(dis[top] + c[i] < dis[to[i]]) {
            dis[to[i]] = dis[top] + c[i];
            if(f[to[i]] == 0) {
              f[to[i]] = 1;
              Q.push(to[i]);
            }
          }
        }
      }
    }
    
    int main() {
      scanf("%d%d", &n, &m);
      for(int i = 1; i <= n; i ++) {
        scanf("%s", name[i]);
        h[i] = -1;
      }
      for(int i = 1; i <= m; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v, cost(u, v));
        add(v, u, cost(u, v));
      }
      scanf("%d%d", &S, &T);
      spfa();
      printf("%d
    ", dis[T]);
      return 0;
    }
    

    D - Husam's Bug

    模拟。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6 + 10;
    char s[maxn];
    
    int main() {
      int T;
      scanf("%d", &T);
      while(T --) {
        scanf("%s", s);
        
        int num1=0, num2=0, num3=0;
        for(int i = 0; s[i];i ++) {
          if(s[i]>='a'&&s[i]<='z') num1++;
          else if(s[i]>='A'&&s[i]<='Z') num1++;
          else if(s[i]>='0'&&s[i]<='9') num2++;
          else if(s[i] =='!' || s[i] =='?'||s[i] == '@') {
            num3++;
          }
        }
        if(num1 < 4) {
          printf("The last character must be a letter.
    ");
          continue;
        }
        if(num2 < 4) {
          printf("The last character must be a digit.
    ");
          continue;
        }
        if(num3 < 2) {
          printf("The last character must be a symbol.
    ");
          continue;
        }
        printf("The last character can be any type.
    ");
      }
      return 0;
    }
    

    E - Abdalrahman Ali Bugs

    由于验证的复杂度只有$O(26)$,因此可以枚举答案。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 10;
    int n, m;
    char s[maxn];
    long long f[maxn];
    
    int main() {
      scanf("%s", s);
      for(int i = 0; s[i]; i ++) {
        f[s[i] - 'a'] ++;
      }
      long long ans = -1;
      long long mn = -1;
      for(long long i = 2; i <= 300000; i ++) {
        long long tmp = 0;
        for(int j = 0; j < 26; j ++) {
          tmp = tmp + (f[j] % i) * f[j];
        }
        if(mn == -1 || tmp < mn) {
          mn = tmp;
          ans = i;
        }
      }
      printf("%lld
    ", ans);
      return 0;
    }
    

    F - Certifications

    二分查找。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 10;
    int n, m;
    int a[maxn];
    
    int main() {
      scanf("%d", &n);
      for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
      sort(a + 1, a + 1 + n);
      scanf("%d", &m);
      while(m --) {
        int x;
        scanf("%d", &x);
        int L = 1, R = n, pos = -1;
        while(L <= R) {
          int mid = (L + R) / 2;
          if(a[mid] >= x) pos = mid, R = mid - 1;
          else L = mid + 1;
        }
        if(pos == -1) printf("Dr. Samer cannot take any offer :(.
    ");
        else printf("%d
    ", a[pos]);
      }
      return 0;
    }
    

    G - In the Chairman's office

    模拟。

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
      int n, m;
      cin>> n>>m;
      if(m % n == 0) printf("YES
    ");
      else printf("NO
    ");
      return 0;
    }
    

    H - Give Me This Pizza

    这题为单调栈经典问题,但是由于数值范围只有$50$,因此可以枚举数值。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5 + 10;
    int n, m;
    int a[maxn];
    int b[maxn];
    int num[maxn];
    
    int main() {
      scanf("%d", &n);
      for(int i = 1; i <= n; i ++) {
        scanf("%d", &a[i]);
      }
      for(int i = 0; i<= 100; i ++) num[i] = 200000;
      for(int j = n; j>=1; j--) {
        b[j] = 200000;
        for(int k = 50; k >= a[j] + 1; k--){
          if(num[k] < b[j]) b[j] = num[k];
        }
        num[a[j]] = j;
        if(b[j] != 200000) b[j] = a[b[j]];
        else b[j] = -1;
      }
      for(int i =1 ;i <= n; i ++) {
        printf("%d ", b[i]);
      }
      return 0;
    }
    

    I - Husam and the Broken Present 1

    对主对角线开根号来求解。

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
      int n;
      cin>> n;
      int x;
      for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j++){
          cin>>x;
          if(i == j){
            int num = sqrt(1.0 * x);
            while(num * num > x) num--;
            while(num*num<x)num++;
            printf("%d ", num);
          }
          
        }
      }
      return 0;
    }
    

    J - Husam and the Broken Present 2

    先删除被包含的那些数组,剩下的可以进行状压$dp$来决策放置顺序。$dp[st][v]$表示有$st$状态里面的子数组已经放置好了,最后放的是$v$的最小花费,和TSP是一样的问题。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1000;
    vector<int> vec[maxn], t[maxn];
    int cost[20][20];
    
    int n;
    int dp[70000][17];
    
    int han(vector<int>& a, vector<int>& b) {
      // a 是否在 b 中
      if(b.size() < a.size()) return 0;
      for(int i = 0; i < b.size(); i ++) {
        int L = i, R = i + a.size() - 1;
        if(R >= b.size()) break;
        int fail = 0;
        for(int j = 0; j < a.size(); j ++) {
          if(a[j] != b[L + j]) fail = 1;
        }
        if(fail == 0) return 1;
      }
      return 0;
    }
    
    int cal(int x, int y) {
      // x 后面 接 y
      int res = 0;
      for(int i = 0; i < t[x].size(); i ++) {
        if(t[x].size() - i > t[y].size()) continue;
        int fail = 0;
        for(int j = i; j < t[x].size(); j ++) {
          if(t[x][j] != t[y][j - i]) fail = 1;
        }
        //printf("!!! %d, %d
    ", i, fail);
        if(fail == 0) {
          res = t[x].size() - i;
          break;
        }
        
      }
      return t[y].size() - res;
    }
    
    bool cmp(const vector<int> &a, const vector<int> &b) {
      return a.size() > b.size();
    }
    
    int main() {
      scanf("%d", &n);
      for(int i = 0; i < n; i ++) {
        int x;
        scanf("%d", &x);
        while(x--){
          int p;
          scanf("%d", &p);
          vec[i].push_back(p);
        }
      }
      sort(vec, vec + n, cmp);
      int sz = 0;
      t[sz++] = vec[0];
      for(int i = 1; i < n; i ++) {
        int fail = 0;
        for(int j = 0; j < sz; j ++) {
          if(han(vec[i], t[j])) {
            fail = 1;
            break;
          }
        }
        if(fail) continue;
        t[sz ++] = vec[i];
      }
      
      n = sz;
      
      /*
      for(int i = 0; i < n; i ++) {
        for(int j = 0; j < t[i].size(); j ++) {
          cout << t[i][j] << " ";
        }
        cout << endl;
      }
       */
      
      for(int i = 0; i < n; i ++) {
        for(int j = 0; j < n; j ++) {
          if(i == j) continue;
          cost[i][j] = cal(i, j);
        }
      }
      
      for(int st = 0; st < (1 << n); st ++) {
        for(int i = 0; i < n; i ++) {
          dp[st][i] = 200000;
        }
      }
      for(int i = 0; i < n; i ++) {
        dp[1 << i][i] = t[i].size();
      }
      
      for(int st = 1; st < (1 << n); st ++) {
        for(int pre = 0; pre < n; pre ++) {
          if(((1 << pre) & st) == 0) continue;
          for(int now = 0; now < n; now ++) {
            if((1 << now) & st) continue;
            dp[st | (1 << now)][now] = min(dp[st | (1 << now)][now], dp[st][pre] + cost[pre][now]);
          }
        }
      }
      
      int ans = dp[(1 << n) - 1][0];
      for(int i = 0; i < n; i ++) {
        ans = min(ans, dp[(1 << n) - 1][i]);
      }
      printf("%d
    ", ans);
      
      return 0;
    }
    
    /*
     3
     2 1 2
     4 3 4 5 6
     3 2 3 4
     
     */
    
  • 相关阅读:
    Entity Framework Core 2.0 新特性
    asp.net core部署时自定义监听端口,提高部署的灵活性
    asp.net core使用jexus部署在linux无法正确 获取远程ip的解决办法
    使用xshell连接服务器,数字键盘无法使用解决办法
    使用Jexus 5.8.2在Centos下部署运行Asp.net core
    【DevOps】DevOps成功的八大炫酷工具
    【Network】Calico, Flannel, Weave and Docker Overlay Network 各种网络模型之间的区别
    【Network】UDP 大包怎么发? MTU怎么设置?
    【Network】高性能 UDP 应该怎么做?
    【Network】golang 容器项目 flannel/UDP相关资料
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8453921.html
Copyright © 2011-2022 走看看