• Round G 2019


    https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050e02/000000000018fd0d

    Book Reading (10pts, 15pts)

    1 ≤ T ≤ 100.
    1 ≤ P1 < P2 < ... < PM ≤ N.
    1 ≤ Ri ≤ N, for all i.

    Test set 1 (Visible)

    1 ≤ M ≤ N ≤ 1000.
    1 ≤ Q ≤ 1000.

    Test set 2 (Hidden)

    1 ≤ M ≤ N ≤ 105.
    1 ≤ Q ≤ 105.

    题意:一本书有 1……n页,撕去 p 页,有 q 个读者, 问读者一共能阅读的页数

    如果直接枚举暴力的话, 10ps 到手

    #include<bits/stdc++.h>
    
    using namespace std;
    #define _for(i,a,b) for(int i = (a); i < (b); i++)
    #define _rep(i,a,b) for(int i = (a); i <= (b); i++)
    const int N = 1e5+100;
    int a[N],b[N],vis[N];
    
    int main(){
        ios::sync_with_stdio(0); cin.tie(0);
        int t,n,m,q,kase = 1; cin >>t ;
        while(t--) {
            cin >> n >> m >> q; int x,cnt = 0;
            memset(vis, 0, sizeof(vis));
            _for(i,0,m) cin >> x, vis[x] = 3;
            _for(i,0,q) {
                cin >> x;
                for(int j = x; j <= n; j += x)
                    if(vis[j] != 3) cnt++;
            }
            
            cout << "Case #"<< kase++ << ": ";
            cout << cnt << endl;
        }
        return 0;
    }
    View Code

    但是很明显, 会 TLE, 所以需要优化下

    #include<bits/stdc++.h>
    
    using namespace std;
    #define _for(i,a,b) for(int i = (a); i < (b); i++)
    #define _rep(i,a,b) for(int i = (a); i <= (b); i++)
    #define ll long long
    const int N = 1e5+100;
    
    int main(){
        ios::sync_with_stdio(0); cin.tie(0);
        int t,n,m,q,kase = 1; cin >>t ;
        while(t--) {
            vector<int> a(N, 0);
            vector<bool> vis(N, false);
            cin >> n >> m >> q; int x;
            ll cnt = 0;
            _for(i,0,m) cin >> x, vis[x] = true;
            _for(i,0,q) {
                cin >> x;
                if(a[x]){
                    cnt += a[x];
                    continue;
                }
                
                for(int j = x; j <= n; j += x)
                    if(!vis[j]) a[x]++;
                cnt += a[x];
            }
            
            cout << "Case #"<< kase++ << ": ";
            cout << cnt << endl;
        }
        return 0;
    }

    https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050e02/000000000018fe36
    The Equation (12pts, 20pts)

    直接暴力 12pts可到手

    #include<bits/stdc++.h>
      
    using namespace std;
      
    const double eps = 1e-10;
    const double pi = 3.1415926535897932384626433832795;
    const double eln = 2.718281828459045235360287471352;
    
    #define scld(x) scanf("%lld", &x)
    #define prcas printf("Case #%d: ", cas)
    #define pncas printf("Case #%d:
    ", cas)
    #define lowbit(x) ((x) & (-(x)))
    #define fi first
    #define se second
    typedef long long LL;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    typedef pair<LL, LL> pll;
    typedef vector<int> vi;
    
    const int maxn = 25;
    int dp[1048550];
    LL a[maxn], b[maxn];
    int n, T, h;
    
    int main()
    {   
        scanf("%d", &T);
        for(int cas = 1; cas <= T; ++ cas)
        {
            scanf("%d %d", &n, &h);
            for(int i = 0; i < n; ++ i) scld(a[i]);
            //for(int i = 0; i < n; ++ i) scld(b[i]);
            prcas; int flag = 0;
            for(int i = 128; i >= 0; i--){
                int sum = 0;
                for(int j = 0; j < n; j++)
                    sum += a[j]^i;
                if(sum <= h) {
                    flag = 1; printf("%d
    ", i);break;
                }
            }
            if(!flag) printf("-1
    ");
        } 
        return 0;
    }

    通过对 k 的二进制位数进行枚举, cnt[i][0]   cnt[i][1]分别记录 数组a的 第i+1位的 0 与 1的个数

    再通过 ret[i][0]  ret[i][1] 分别表示对前 i 位的a数组的 0 与 1 表示的和

    然后 通过 suf[i] 记录前 i 项 min(ret[i][0], ret[i][1])的和, (???)
    然后枚举 位数 i 51~0 如果符合 ret[i][1]+suf[i-1]  k |= 1<<i , 即 k 的这个二进制位为 1, 否则为 0  m-= ( 为1 ? ret[i][1] : ret[i][0])
    若枚举结束  m < 0, 则不存在 k

    #include<bits/stdc++.h>
    
    using namespace std;
    #define ll long long
    const int N = 52;
    int cnt[N+2][2];
    ll suf[N+2], ret[N+2][2];
    int main(){
        int t; cin >> t;
        for(int kase = 1; kase <= t; kase++){
            int n; ll k,m,ans = 0;
            cin >> n >> m;
            for(int i = 0; i < N; i++) cnt[i][0] = cnt[i][1] = 0;
            while(n--) {
                cin >> k;
                for(int j = 0; j < N; j++, k >>= 1) 
                    cnt[j][k&1]++;
            }
    //for(int i = 0; i < N; i++) cout << cnt[i][0] << " " << cnt[i][1] << "	";cout<<endl;cout << endl;
            for(int i = 0; i < N; i++)
                ret[i][0] = 1ll*cnt[i][1]*(1ll<<i), 
                ret[i][1] = 1ll*cnt[i][0]*(1ll<<i);
    //for(int i = 0; i < N; i++) cout << ret[i][0] << " " << ret[i][1] << "	";cout<<endl; cout << endl;
            suf[0] = min(ret[0][0], ret[0][1]);
            for(int i = 1; i < N; i++)
                suf[i] = suf[i-1]+min(ret[i][0], ret[i][1]);
    
    //for(int i = 0; i < N; i++) cout << suf[i] << "	"; cout << endl; cout << endl;
    
            for(int i = N-1; i >= 0 && m >= 0; i--){// mofa
                ll t = 0;
                if(i > 0) t = suf[i-1];
                if(t+ret[i][1] <= m){
                    m -= ret[i][1];
                    ans |= (1ll<<i);
                }else m -= ret[i][0];
                
            }
            if(m < 0) ans = -1;
            cout << "Case #" << kase << ": ";
            cout << ans << endl;
        }
        return 0;
    }
    View Code

    https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050e02/000000000018fd5e
    Shifts (20pts, 23pts)

    题意:有n个班次, h 快乐值要求, 问有多少种情况 a 与 b 都快乐(快乐值大于等于h)

    如果直接暴力的话, 0~ 3^n-1, 暴力枚举 每个班次的三种情况(单选a, 单选b, 同时选ab),n<=12,5e5的样子,能过 Test set 1, 但Test set 2 3e8(n<=20)就会TLE

     TLE

      #include<bits/stdc++.h>
      using namespace std;
      #define rep(x,y) for(long long i =x;i<=y;i++)
      #define pb push_back
      #define mp make_pair
      #define ALL(x) (x).begin(),(x).end()
      #define FastIO  ios_base::sync_with_stdio(false); cin.tie(NULL);
      typedef long long ll;
      typedef pair< ll, ll> pll;
      typedef vector< ll > vll;
      typedef map < ll, ll > mll;
    
    int main()
    {
      ll i,j,t,test,ans,n,num,s1,s2,a[30],b[30],h,ways;
      test=1;
      cin >> t;
      while(t--)
      {
        cout << "Case #" << test << ": " ;
        ans=0;
        test++;
        cin >> n >> h;
        rep(1,n)
          cin >> a[i];
        rep(1,n)
          cin >> b[i];
        ways= pow(3,n)-1;
        rep(0,ways)
        {
          num=i;
          j=1;
          s1=0;
          s2=0;
          while(j<=n)
          {
            if(num%3==0)
            {
              s1+=a[j];
            }
            else if(num%3==1)
              s2+=b[j];
            else
            {
              s1+=a[j];
              s2+=b[j];
            }
            num/=3;
            j++;
          }
        //  cout << s1 << " " << s2 << endl;
          if(s1>=h && s2>=h)  ans++;
        }
        cout << ans << endl;
      }
      return 0;
    }
    View Code

    dp[mask]  mask 0~2^n-1, 以0 1 分 n个a是否被取
    then  mask 0~2^n-1  i 0~n  dp[mask^(1<<i)] += dp[mask]

    then  x 0~2^n-1  dp[x]  2^n-x-1(二进制01 代表n个b是否被取)    神奇的穷举操作
    最后会发现 所有的可能 3^n 都被枚举了

    比如说 n = 2, 
                a           b

    dp[0] = 00 01 10 11    11

    dp[1] = 01 11      10

    dp[2] = 10 11      01

    dp[3] = 11        00

    #include<bits/stdc++.h>
      
    using namespace std;
      
    const double eps = 1e-10;
    const double pi = 3.1415926535897932384626433832795;
    const double eln = 2.718281828459045235360287471352;
    
    #define scld(x) scanf("%lld", &x)
    #define prcas printf("Case #%d: ", cas)
    #define pncas printf("Case #%d:
    ", cas)
    #define lowbit(x) ((x) & (-(x)))
    #define fi first
    #define se second
    typedef long long LL;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    typedef pair<LL, LL> pll;
    typedef vector<int> vi;
    
    const int maxn = 25;
    int dp[1048550];
    LL a[maxn], b[maxn];
    int n, T, h;
    
    int main()
    {   
        scanf("%d", &T);
        for(int cas = 1; cas <= T; ++ cas)
        {
            scanf("%d %d", &n, &h);
            for(int i = 0; i < n; ++ i) scld(a[i]);
            for(int i = 0; i < n; ++ i) scld(b[i]);
            for(int mask = 0; mask < (1 << n); ++ mask)
            {
                LL sum = 0;
                for(int i = 0; i < n; ++ i) 
                    if((mask >> i) & 1) sum += a[i];
                if(sum >= h) dp[mask] = 1; else dp[mask] = 0;
            }
    //for(int mask = 0; mask < (1 << n); ++ mask) printf("dp[%d]= %d  ", mask, dp[mask]);printf("
    ");
            for(int i = 0; i < n; ++ i)
                for(int mask = 0; mask < (1 << n); ++ mask)
                    if((mask >> i) & 1) dp[mask ^ (1 << i)] += dp[mask];
            LL ans = 0;
    //for(int mask = 0; mask < (1 << n); ++ mask) printf("dp[%d]= %d  ", mask, dp[mask]);printf(" 	...
    ");
            for(int mask = 0; mask < (1 << n); ++ mask)
            {
                LL sum = 0, task = 0;
                for(int i = 0; i < n; ++ i)
                    if((mask >> i) & 1) sum += b[i];
                    else task |= (1 << i);
                if(sum < h) continue;
                ans += dp[task];
            }
            prcas; printf("%lld
    ", ans);
        } 
        return 0;
    }
  • 相关阅读:
    log记录日志使用说明
    浅谈WebService开发三(动态调用WebService)转
    浅谈WebService开发二(同步与异步调用)转
    浅谈WebService开发(一)转
    Log4net使用(二)
    Log4net使用(一)
    创建DSN
    Oracle的substr函数简单用法(转)
    医院里的CR、DR、CT、磁共振、B超都是什么?
    lambda表达式(2)
  • 原文地址:https://www.cnblogs.com/163467wyj/p/11728925.html
Copyright © 2020-2023  润新知