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
     
     */
    
  • 相关阅读:
    关于 Android 进程保活,你所需要知道的一切【转】
    android 按返回键最小化(后台运行)
    android notification完全解析【转】
    使用WakeLock使Android应用程序保持后台唤醒
    [Linux]Vim基本操作
    [STL]map的使用
    [python]使用python进行LINUX系统操作
    python challenge 2:迭代与列表
    python challenge 1、3:字符串处理
    python challenge 0:操作符与内建函数
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8453921.html
Copyright © 2011-2022 走看看