zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第九场)

    AEFIK

    A. Groundhog and 2-Power Representation

    题意

    一个数可以由2x1+2x2+2x3+.....组成,例如1315=210+28+25+2+1=2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0).
    现在给出一个由2的次幂组成的表达式,输出这个数是多少。

    题解

    不得不说py真的强,看到不到2分钟就有人a了,还以为是原题,赛后发现py三行。(暴风哭泣
    我队用的c++高精度模拟写的,队友%%%

    代码

    py
    1 n = input()
    2 n = n.replace("(","**(")
    3 print(eval(n))
    View Code

    c++

      1 #include<bits/stdc++.h>
      2 #define pb push_back
      3 using namespace std;
      4 typedef long long ll;
      5 const int inf = 0x3f3f3f3f;
      6 const ll INF = 0x3f3f3f3f3f3f3f3f;
      7 const int maxn = 3e4+10;
      8  
      9 vector<int> mult(vector<int>x,vector<int>y)//高精*高精
     10 {
     11     int xlen=(int)x.size(),ylen=(int)y.size(),zlen=xlen+ylen;
     12     vector<int>z(zlen);
     13     for(register int i=0;i<xlen;i++)
     14         for(register int j=0;j<ylen;j++)
     15             z[i+j]+=x[i]*y[j];
     16     for(register int i=0;i<zlen;i++)
     17         if(z[i]>9)
     18         {
     19             z[i+1]+=z[i]/10;
     20             z[i]%=10;
     21         }
     22     while(zlen>1 && !z.back())
     23     {
     24         z.pop_back();
     25         zlen--;
     26     }
     27     return z;
     28 }
     29 vector<int> chu(int x,vector<int> vv)
     30 {
     31     bool flag=false;
     32     vector<int> ans;
     33     int t=0;
     34     int i;
     35     for (i=vv.size()-1; i>=0; i-- )
     36     {
     37         t=t*10+vv[i];
     38         if(flag)
     39         {
     40             ans.push_back(t/x);
     41         }
     42         else if(t/x>0)
     43         {
     44             flag=true;
     45             ans.push_back(t/x);
     46         }
     47         t=t%x;
     48     }
     49     return vector<int> (ans.rbegin(),ans.rend());
     50 }
     51 vector<int> add(vector<int>x,vector<int>y)//高精+高精
     52 {
     53     int xlen=(int)x.size(),ylen=(int)y.size(),zlen=max(xlen,ylen)+1;
     54     vector<int>z(zlen);
     55     for(register int i=0;i<zlen;i++)
     56     {
     57         if(i<xlen)
     58             z[i]+=x[i];
     59         if(i<ylen)
     60             z[i]+=y[i];
     61         if(z[i]>9)
     62         {
     63             z[i+1]++;
     64             z[i]-=10;
     65         }
     66     }
     67     while(zlen>1 && !z.back())
     68     {
     69         zlen--;
     70         z.pop_back();
     71     }
     72     return z;
     73 }
     74 void prin(vector<int> x)
     75 {
     76     int i;
     77     if(x.size() == 0)
     78     {
     79         printf("0");
     80     }
     81     for (i=x.size()-1;i>=0;i--)
     82     {
     83         printf("%d",x[i]);
     84     }
     85     printf("
    ");
     86 }
     87 std::vector<int> qup(std::vector<int> vv)
     88 {
     89     std::vector<int> ans;
     90     ans.pb(1);
     91     std::vector<int> v;
     92     std::vector<int> f;
     93     f.pb(0);
     94     v.pb(2);
     95     while(vv.size() > 0 && *(--vv.end()) != 0)
     96     {
     97         if(vv[0] & 1)
     98             ans = mult(v,ans);
     99         vv = chu(2,vv);
    100         v = mult(v,v);
    101     }
    102     return ans;
    103 }
    104  
    105 char a[maxn];
    106 vector<int> dg(int l,int r)
    107 {
    108     vector<int> ans;
    109      
    110     if(l == r)
    111     {
    112         ans.pb(a[l] - '0');
    113         return ans;
    114     }
    115     ans.pb(0);
    116     std::vector<int> temp;
    117     for (int i = l; i <= r; i ++ )
    118     {
    119          
    120         if(a[i] == '(')
    121         {
    122             int s= 0 ;
    123             for(int j = i + 1; j <= r; j ++ )
    124             {
    125                 if(a[j] == '(')
    126                     s ++ ;
    127                 if(a[j] == ')')
    128                 {
    129                     if(s == 0)
    130                     {
    131                         ans = add(ans,qup(dg(i + 1, j - 1)));
    132                         i = j;
    133                         break;
    134                     }
    135                     else
    136                         s -- ;
    137                 }
    138             }
    139             continue;
    140         }
    141         if(a[i] == '+')
    142         {
    143             ans = add(ans,dg(i + 1,r));
    144             break;
    145         }
    146         else
    147         {
    148             if(a[i + 1] != '(')
    149             {
    150                 temp.pb(a[i] - '0');
    151                 ans = add(ans,temp);
    152             }
    153             continue;
    154         }
    155     }
    156     return ans;
    157 }
    158  
    159 int main()
    160 {
    161     scanf("%s",a + 1);
    162     int n = strlen(a + 1);
    163     vector<int> ans = dg(1,n);
    164     prin(ans);
    165 }
    View Code

    E. Groundhog Chasing Death

    题意

    给出a,b,c,d,x,y,求∏(i=a,b)(j=c,d) gcd(xi,yj)  modulo 998244353的结果

    题解

    第一想法肯定是暴力:枚举 i 和 j ,然后算出每一个 gcd(x, yj),然后乘起来。但是数据 i 和 j 的数据范围都在1e6,这样肯定会超时,i 和 j 的范围在1e9,这样肯定是要爆long long的。那么就要想想怎么优化。
    因为这是一个乘性函数,那么肯定要想到分解质因子,所以先预处理 x 的质因子,并记录每个质因子出现的次数,这样 x就可以由每个质因子个数再 *i 得到。枚举 x中因子 m 出现的次数,可以发现当 yj 小的时候,gcd(x, yj) 主要是被 yj 的 m 个数约束,此时是一个等差数列;当 yj 大的时候,就是由 x约束,此时 yj 中 m 的个数是一个常数,暴力求解就好了。
    由于质因子的幂很大,会爆long long,所以要用欧拉降幂,欧拉降幂是对mod-1取模(队友对mod取模debug好久

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3  
      4 typedef long long ll;
      5 const ll mod = 998244353;
      6 const ll md = 998244352;
      7 vector<pair<ll,ll> > v;
      8  
      9 void div(ll n)
     10 {
     11     v.clear();
     12     ll k = sqrt(n);
     13     for (ll i = 2; i <= k; ++ i) {
     14         ll cnt = 0;
     15         while (n % i == 0) {
     16             n /= i;
     17             cnt ++;
     18         }
     19         v.push_back({i, cnt});
     20     }
     21     if (n != 1) {
     22         v.push_back({n, 1});
     23     }
     24 }
     25  
     26 ll phi(ll n)
     27 {
     28     ll ans = n;
     29     ll k = sqrt(n);
     30     for (int i = 2; i <= k; ++i) {
     31         if (n % i == 0) {
     32             ans = ans / i * (i - 1);
     33             while (n % i == 0) n /= i;
     34         }
     35     }
     36     if (n > 1) {
     37         ans = ans / n * (n - 1);
     38     }
     39     return ans;
     40 }
     41  
     42 ll pow(ll a, ll b, ll p) {
     43     ll res = 1;
     44     while (b) {
     45         if (b & 1) res = (res * a) % p;
     46         a = a * a % p;
     47         b >>= 1;
     48     }
     49     return res%p;
     50 }
     51  
     52 int main()
     53 {
     54     ll a, b, c, d, x, y;
     55     scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &x, &y);
     56     a = max(1LL, a);
     57     c = max(1LL, c);
     58     --c;
     59     div(x);
     60     ll ans = 1;
     61     for (int i = 0; i < (int)v.size(); ++ i) {
     62         ll cnt = 0;
     63         while (y % v[i].first == 0) {
     64             y /= v[i].first;
     65             ++ cnt;
     66         }
     67         ll sum = 0;
     68         if (cnt == 0) continue;
     69         for (ll j = a; j <= b; ++ j) {
     70             ll e = v[i].second * (ll)j;
     71             ll f = e/cnt;
     72             while (cnt * f < e) {
     73                 ++ f;
     74             }
     75             if (c >= f) {
     76                 sum -= ((f * (f-1) / 2)% md * (cnt % md)) % md;
     77                 sum = (sum % md + md) % md;
     78                 sum -= (ll)(((c-f+1) % md) * (e % md)) % md;
     79                 sum = (sum % md + md) % md;
     80             }
     81             else {
     82                 sum -= ((c * (c+1) / 2) % md * (cnt % md)) % md;
     83                 sum = (sum % md + md) % md;
     84             }
     85             sum = (sum % md + md) % md;
     86             if (d >= f) {
     87                 sum += ((f * (f-1) / 2) % md) * (cnt % md) % md;
     88                 sum = (sum % md + md) % md;
     89                 sum += (ll)(((d-f+1) % md) * (e % md)) % md;
     90                 sum = (sum % md + md) % md;
     91             }
     92             else {
     93                 sum += (((d * (d+1) /2) % md) * (cnt) % md) % md;
     94                 sum = (sum % md + md) % md;
     95             }
     96         }
     97         sum = (sum % md + md) % md;
     98         ans *= pow(v[i].first, sum, mod);
     99         ans = (ans % mod + mod) % mod;
    100     }
    101     ans = (ans % mod + mod) % mod;
    102     printf("%lld
    ", ans);
    103     return 0;
    104 }
    View Code

    F. Groundhog Looking Dowdy

    题意

    土拨鼠要和苹果约会,第 i 天它的第 j 件衣服的邋遢度为 aij ,它要在n天中选择m天和苹果约会,要求选出的m天衣服的邋遢度的最大值和最小值的差值最小。

    题解

    因为要最小化最大值和最小值的差值,所以用pair存每件衣服的邋遢度和第几天,然后对邋遢度从小到大排序。那么问题就转换成了求一个区间 [L,R] ,使得这个区间覆盖m个不同的天,并且R的邋遢度-L的邋遢度最小。这个问题就可以用尺取解决了。对于每一个L,求出最小的合法的R,每次更新差值最小值即可。

    代码

     1 #include<bits/stdc++.h>
     2 #define st first
     3 #define sd second
     4 #define ll long long
     5 #define pii pair<int,int>
     6 using namespace std;
     7  
     8 const int inf = 0x3f3f3f3f;
     9 const int maxn = 2e6+10;
    10  
    11 pii pp[maxn];
    12 int vis[maxn];
    13  
    14 int main()
    15 {
    16     int n,m;
    17     scanf("%d%d",&n,&m);
    18     int cnt = 0;
    19     for (int i = 1; i <= n; i ++ ){
    20         int p;
    21         scanf("%d",&p);
    22         for (int j = 1; j <= p; j ++ ){
    23             int x;
    24             scanf("%d",&x);
    25             pp[++cnt].st = x;
    26             pp[cnt].sd = i;
    27         }
    28     }
    29     sort(pp + 1, pp + 1 + cnt);
    30     int num = 0;
    31     int l = 1, r = 1;
    32     int minn = pp[1].st, maxx = 0;
    33     int ans = inf;
    34     while(1){
    35         while(r <= cnt && num < m){
    36             if(vis[pp[r].sd] == 0) num ++ ;
    37             vis[pp[r].sd] ++ ;
    38             maxx = pp[r].st;
    39             r ++ ;
    40         }
    41         if(num < m)
    42             break;
    43         ans = min(ans, maxx - minn);
    44         vis[pp[l].sd] -- ;
    45         if(vis[pp[l].sd] == 0) num -- ;
    46         minn = pp[l + 1].sd;
    47         l ++ ;
    48     }
    49     printf("%d
    ",ans);
    50 }
    View Code

    I. The Crime-solving Plan of Groundhog

    题意

    给出n个数(0<=a[i]<=9),由这n个数组成2个数,使得这两个数的乘积最小。

    题解

    自己造几个例子就可以看出,选择0之外最小的数和剩下的数字组成的没有前导0的数相乘结果最小。剩下的数字怎样最小呢,当然是找到最小的非零的数做第一位,后边接上所有的0,再按照有小到大的顺序放剩下的数字。因为n的范围在1e5,所以要用高精度乘法。

    推导:

    把当前的数字拆成4个数 a, b, c, d (a ≤ b ≤ c ≤ d) ,那么我们有两种决策:两位数×两位数,或者三位数×一
    位数。
    (10a + d) * (10b + c) = 100ab + 10ac + 10bd + cd 
    (100b+10c+d) * a = 100ab + 10ac +ad<(10a + d) * (10b + c)
    同理,可以证明留一个最小的正整数作为第一个数,剩下的所有数字排成最小的数作为第二个数时,答案取到最小值。

    代码

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4  
     5 int a[100100];
     6  
     7 int main()
     8 {
     9     ios::sync_with_stdio(false);
    10     cin.tie(0);
    11     cout.tie(0);
    12     int t;
    13     cin>>t;
    14     while(t--){
    15         int n;
    16         cin>>n;
    17         for(int i=0;i<n;i++) cin>>a[i];
    18         sort(a,a+n);
    19         int k=0;
    20         while(k<n&&a[k]==0) k++;
    21         vector<int>q;
    22         q.push_back(a[k+1]);
    23         for(int i=0;i<k;i++) q.push_back(0);
    24         for(int i=k+2;i<n;i++) q.push_back(a[i]);
    25         vector<int>ans;
    26         for(int i=q.size()-1;i>=0;i--){
    27             int x=q[i]*a[k];
    28             ans.push_back(x);
    29         }
    30         for(int i=0;i<10;i++) ans.push_back(0);
    31         for(int i=0;i<ans.size();i++){
    32             if(ans[i]>=10){
    33                 ans[i+1]+=ans[i]/10;
    34                 ans[i]%=10;
    35             }
    36         }
    37         while(!ans.back()) ans.pop_back();
    38         for(int i=ans.size()-1;i>=0;i--) cout<<ans[i];
    39         cout<<endl;
    40     }
    41     return 0;
    42 }
    View Code

    K. The Flee Plan of Groundhog

    题意

    土拨鼠在第1个宿舍,橙子在第n个宿舍。这n个宿舍间有n-1条路并且长度都为1,土拨鼠从第1个房间去第n个宿舍,速度为1m/s;橙子从第n个宿舍追赶土拨鼠,速度为2m/s。

    题解

    二分时间 t ,然后判断在 ts 内土拨鼠是否会被橙子追上。以橙子所在的寝室 n 为根建树,从 1 到 n 枚举所有土拨鼠能够到达的点,先找出t秒能走到哪个点,然后再找这个点能走到的离n最远的点,判断在走的过程中会不会被追上。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3  
     4 const int maxn = 1e5+10;
     5 vector<int> vv[maxn];
     6 int vis[maxn];
     7 int f[maxn];
     8 int dep[maxn];
     9  
    10 void dfs(int x,int fa,int de)
    11 {
    12     f[x] = fa;
    13     dep[x] = de;
    14     for (int i =0 ; i< vv[x].size(); i ++ )
    15     {
    16         int v = vv[x][i];
    17         if(v == fa)
    18             continue;
    19         dfs(v,x,de + 1);
    20         vis[x] |= vis[v];
    21     }
    22 }
    23 int ans =0 ;
    24 void dfs2(int x,int fa,int de)
    25 {
    26     ans = max(ans,de);
    27     for (int i =0 ; i<vv[x].size(); i ++ )
    28     {
    29         int v = vv[x][i];
    30         if(v == fa)
    31             continue;
    32         dfs2(v,x,de + 1);
    33     }
    34  
    35 }
    36 int main()
    37 {
    38     int n,m;
    39     scanf("%d%d",&n,&m);
    40     for (int i = 1; i < n; i ++ )
    41     {
    42         int x,y;
    43         scanf("%d%d",&x,&y);
    44         vv[x].push_back(y);
    45         vv[y].push_back(x);
    46     }
    47     vis[1] = 1;
    48     dfs(n,0,1);
    49     int k = -1;
    50     int s = dep[1] - m;
    51     for (int i = 1; i <= n; i ++ ){
    52         if(vis[i] && dep[i] == s){
    53             k = i;
    54             break;
    55         }
    56     }
    57     int num = dep[k] - 1;
    58     dfs2(k,f[k],1);
    59     ans -- ;
    60     num += ans;
    61     int r = (num + 1) / 2;
    62     int l = 0;
    63     while(l < r){
    64         int mid = l + r>> 1;
    65         int x = min(2 * mid,num);
    66         int y = min(mid, ans);
    67         if(x - dep[k] + 1>= y) r = mid;
    68         else l = mid + 1;
    69     }
    70     printf("%d
    ",l);
    71 }
    View Code
  • 相关阅读:
    【转】Android Lint分类及常见错误
    备忘
    【转】QRCode二维码生成方案及其在带LOGO型二维码中的应用
    如何控制横向和纵向滚动条的显隐?
    网页屏保
    过度方式
    让背景图不滚动
    自定义指定区域的文字大小
    定义本网页关键字
    通过层来实现渐淡淡出
  • 原文地址:https://www.cnblogs.com/lilibuxiangtle/p/13463710.html
Copyright © 2011-2022 走看看