zoukankan      html  css  js  c++  java
  • 2017"百度之星"程序设计大赛

    Arithmetic of Bomb

     
     Accepts: 1050
     
     Submissions: 1762
     Time Limit: 2000/1000 MS (Java/Others)
     
     Memory Limit: 32768/32768 K (Java/Others)
    Problem Description

    众所周知,度度熊非常喜欢数字。

    它最近在学习小学算术,第一次发现这个世界上居然存在两位数,三位数……甚至N位数!

    但是这回的算术题可并不简单,由于含有表示bomb的#号,度度熊称之为 Arithmetic of Bomb。

    Bomb Number中的bomb,也就是#号,会展开一些数字,这会导致最终展开的数字超出了度度熊所能理解的范畴。比如”(1)#(3)”表示”1”出现了3次,将会被展开为”111”,

    同理,”(12)#(2)4(2)#(3)”将会被展开为”12124222”。

    为了方便理解,下面给出了Bomb Number的BNF表示。

    <bomb number> := <bomb term> | <bomb number> <bomb term> <bomb term> := <number> | '(' <number> ')' '#' '(' <non-zero-digit> ')' <number> := <digit> | <digit> <number> <digit> := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' <non-zero-digit> := '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

    请将Bomb Number中所有的#号展开,由于数字可能很长,结果对 1 000 000 007 取模。

    Input

    第一行为T,表示输入数据组数。

    每组数据包含一个Bomb Expression。

    • 1≤T≤100

    • 1≤length(Bomb Number)≤1000

    Output

    对每组数据输出表达式的结果,结果对 1 000 000 007 取模。

    Sample Input
    4
    1
    (1)#(3)
    (12)#(2)4(2)#(3)
    (12)#(5)
    
    Sample Output
    1
    111
    12124222
    212121205

    #include <bits/stdc++.h>
    using namespace std;
    const int MD=1e9+7;
    int c[10005];
    char s[10005];
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",s+1);
            int ans=0;
            for(int i=1;s[i];)
            {
                if(s[i]=='(')
                {
                    int j=i+1,n2=0,n=0;
                    while(s[j]!=')')
                    {
                        c[++n]=s[j]-48;
                        j++;
                    }
                    j+=3;
                    while(s[j]!=')')
                    {
                        n2=n2*10+s[j]-48;
                        j++;
                    }
                    for(int j=n+1;j<=n*n2;j++)
                    c[j]=c[(j-1)%n+1];
                    for(int j=1;j<=n*n2;j++)
                    ans=(1ll*ans*10+c[j])%MD;
                    i=j+1;
                }
                else
                {
                    int j=i;
                    int n=0;
                    while(s[j]!='('&&s[j])
                    {
                        c[++n]=s[j]-48;
                        j++;
                    }
                    for(int j=1;j<=n;j++)
                    ans=(1ll*ans*10+c[j])%MD;
                    i=j;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    Pokémon GO

     
     Accepts: 738
     
     Submissions: 1725
     Time Limit: 3000/1500 MS (Java/Others)
     
     Memory Limit: 32768/32768 K (Java/Others)
    Problem Description

    众所周知,度度熊最近沉迷于 Pokémon GO。

    今天它决定要抓住所有的精灵球!

    为了不让度度熊失望,精灵球已经被事先放置在一个2*N的格子上,每一个格子上都有一个精灵球。度度熊可以选择任意一个格子开始游戏,抓捕格子上的精灵球,然后移动到一个相邻的至少有一个公共点的格子上继续抓捕。例如,(2, 2) 的相邻格子有(1, 1), (2, 1) 和 (1, 2) 等等。

    现在度度熊希望知道将所有精灵球都抓到并且步数最少的方案数目。两个方案被认为是不同,当且仅当两个方案至少有一步所在的格子是不同的。

    Input

    第一行为T,表示输入数据组数。

    每组数据包含一个数N。

    ●1≤T≤100

    ●1≤N≤10000

    Output

    对每组数据输出方案数目,结果对 1 000 000 007 取模。

    Sample Input
    3
    1
    2
    3
    
    Sample Output
    2
    24
    96

    #include <bits/stdc++.h>
    using namespace std;
    typedef __int64 LL;
    const int N=1e4+5;
    const LL MD=1e9+7;
    LL f[N],dp[N];
    int main()
    {
        f[0]=1;
        f[1]=2;
        for(int i=2; i<N; i++)
            f[i]=(f[i-1]<<1)%MD;
        dp[0]=0;
        dp[1]=0;
        for(int i=2; i<N; i++)
            dp[i]=(4*(f[i-2]+dp[i-2])+2*(f[i-1]+dp[i-1]))%MD;
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n;
            scanf("%d",&n);
            LL ans=0;
            for(int i=1;i<=n;i++)
            {
                if(i==1||i==n)
                {
                    ans=(ans+f[n]+dp[n])%MD;
                }
                else
                {
                    ans=(ans+f[i]*(f[n-i]+dp[n-i])%MD)%MD;
                    ans=(ans+f[n-i+1]*(f[i-1]+dp[i-1])%MD)%MD;
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    Valley Numer

     
     Accepts: 548
     
     Submissions: 1125
     Time Limit: 2000/1000 MS (Java/Others)
     
     Memory Limit: 32768/32768 K (Java/Others)
    Problem Description

    众所周知,度度熊非常喜欢数字。

    它最近发明了一种新的数字:Valley Number,像山谷一样的数字。

    当一个数字,从左到右依次看过去数字没有出现先递增接着递减的“山峰”现象,就被称作 Valley Number。它可以递增,也可以递减,还可以先递减再递增。在递增或递减的过程中可以出现相等的情况。

    比如,1,10,12,212,32122都是 Valley Number。

    121,12331,21212则不是。

    度度熊想知道不大于N的Valley Number数有多少。

    注意,前导0是不合法的。

    Input

    第一行为T,表示输入数据组数。

    每组数据包含一个数N。

    ● 1≤T≤200

    ● 1≤length(N)≤100

    Output

    对每组数据输出不大于N的Valley Number个数,结果对 1 000 000 007 取模。

    Sample Input
    3
    3
    14
    120
    
    Sample Output
    3
    14
    119

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const ll mod = 1e9 + 7;
    
    string s;
    ll dp[105][10][3][2][2];
    
    int dfs(int p, int now, int sta, int f, int st) {
      if (p == s.size()) return 1;
      if (dp[p][now][sta][f][st] != -1) return dp[p][now][sta][f][st];
      ll& ret = dp[p][now][sta][f][st];
      ret = 0;
      for (int i = 0; i <= (f ? s[p] - '0' : 9); i++) {
        if (sta == 1) {
          ret = (ret + dfs(p + 1, (i == 0 && st ? 9 : i), (i <= now ? 1 : 2), f && i == s[p] - '0', st && i == 0)) % mod;
        }
        if (sta == 2 && i >= now) {
          ret = (ret + dfs(p + 1, (i == 0 && st ? 9 : i), 2, f && i == s[p] - '0', st && i == 0)) % mod;
        }
      }
      return ret;
    }
    
    int main(int argc, char *argv[]) {
      int T;
      cin >> T;
      while (T--) {
        memset(dp, -1, sizeof(dp));
        cin >> s;
        cout << (dfs(0, 9, 1, 1, 1) + mod - 1) % mod << endl;
      }
      return 0;
    }

    alley Numer II

     
     Accepts: 161
     
     Submissions: 538
     Time Limit: 12000/6000 MS (Java/Others)
     
     Memory Limit: 32768/32768 K (Java/Others)
    Problem Description

    众所周知,度度熊非常喜欢图。

    它最近发现了图中也是可以出现 valley —— 山谷的,像下面这张图。

    为了形成山谷,首先要将一个图的顶点标记为高点或者低点。标记完成后如果一个顶点三元组<X, Y, Z>中,X和Y之间有边,Y与Z之间也有边,同时X和Z是高点,Y是低点,那么它们就构成一个valley。

    度度熊想知道一个无向图中最多可以构成多少个valley,一个顶点最多只能出现在一个valley中。

    Input

    第一行为T,表示输入数据组数。

    每组数据的第一行包含三个整数N,M,K,分别表示顶点个数,边的个数,标记为高点的顶点个数。

    接着的M行,每行包含两个两个整数Xi,Yi,表示一条无向边。

    最后一行包含K个整数Vi,表示这些点被标记为高点,其他点则都为低点。

    ● 1≤T≤20

    ● 1≤N≤30

    ● 1≤M≤N*(N-1)/2

    ● 0≤K≤min(N,15)

    ● 1≤Xi, Yi≤N, Xi!=Yi

    ● 1≤Vi≤N

    Output

    对每组数据输出最多能构成的valley数目。

    Sample Input
    3
    3 2 2
    1 2
    1 3
    2 3
    3 2 2
    1 2
    1 3
    1 2
    7 6 5
    1 2
    1 3
    1 4
    2 3
    2 6
    2 7
    3 4 5 6 7
    
    Sample Output
    1
    0
    2

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int main(int argc, char *argv[]) {
      int T;
      cin >> T;
      while (T--) {
        int n, m, K;
        cin >> n >> m >> K;
        vector<vector<int>> g(n);
        vector<int> vis(n);
        for (int i = 0; i < m; i++) {
          int u, v;
          cin >> u >> v;
          u--, v--;
          //      cout << u << " " << v << endl;
          g[u].push_back(v);
          g[v].push_back(u);
        }
        for (int i = 0; i < K; i++) {
          int v;
          cin >> v;
          vis[v - 1] = i + 1;
        }
        vector<vector<int>> dp(n + 1, vector<int>(1 << K));
        dp[0][0] = 1;
        for (int i = 0; i < n; i++) {
          if (vis[i]) dp[i + 1] = dp[i];
          else {
            dp[i + 1] = dp[i];
            vector<pair<int, int>> vec;
            //        cout << g[i].size() << endl;
            for (int v1 : g[i]) {
              for (int v2 : g[i]) {
                if (v1 != v2 && vis[v1] && vis[v2]) {
                  vec.push_back({vis[v1] - 1, vis[v2] - 1});
                }
              }
            }
            for (int j = 0; j < (1 << K); j++) {
              if (dp[i][j]) {
                for (auto e : vec) {
                  int x = e.first, y = e.second;
                  if (!((1 << x) & j) && !((1 << y) & j)) {
                    dp[i + 1][j | (1 << x) | (1 << y)] = 1;
                  }
                }
              }
            }
          }
        }
        int mx = 0;
        for (int i = 0; i < (1<<K); i++) {
          if (dp[n][i]) {
            int cnt = 0;
            for (int j = 0; j < K; j++) {
              if ((1 << j) & i) {
                cnt++;
              }
            }
            mx = max(mx, cnt);
          }
        }
        cout << mx / 2 << endl;
      }
      return 0;
    }
  • 相关阅读:
    克罗内克符号
    子进程和线程
    力扣:数学问题
    iconv装换文件编码格式
    mac 上iterm终端显示中文为乱码解决方案
    Android启动时间测试方法
    Centos4.3安装MySQL-python-1.2.3,出现error: command 'gcc' failed with exit status 1
    java mail发送邮件
    Java通过socket实现smtp协议发送邮件
    vim解决中文显示乱码问题
  • 原文地址:https://www.cnblogs.com/BobHuang/p/8522411.html
Copyright © 2011-2022 走看看