zoukankan      html  css  js  c++  java
  • “玲珑杯”ACM比赛 Round #13 题解&源码

     A

     

    题目链接:http://www.ifrog.cc/acm/problem/1111

    分析:容易发现本题就是排序不等式, 将A数组与B数组分别排序之后, 答案即Ni=1Ai×Bi

    此题有坑,反正据我提交而言,一直RE,之后发现两个地方会出错,一是定义数组要放在main函数之前,第二是ans+=1LL*a[i]*b[i],如果少了1LL,结果肯定WA,这就是此题的亮点所在!

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std ;
     4 
     5 typedef long long LL ;
     6 
     7 const int MAXN = 500010 ;
     8 
     9 int n ; 
    10 
    11 int a[MAXN], b[MAXN] ; 
    12 
    13 int main() { 
    14         scanf("%d", &n) ;
    15         for (int i = 1; i <= n; i ++) scanf("%d", &a[i]) ; 
    16         for (int i = 1; i <= n; i ++) scanf("%d", &b[i]) ;
    17         sort(a + 1, a + n + 1) ;
    18         sort(b + 1, b + n + 1) ; 
    19         LL ans = 0 ; 
    20         for (int i = 1; i <= n; i ++) ans += 1LL * a[i] * b[i] ; 
    21         cout << ans << endl ; 
    22 }

    B

    题目链接:http://www.ifrog.cc/acm/problem/1112

    分析:

    一个显然的想法是每一次二分加入到第几个数的时候, 混乱度超过M, 然后暴力检验, 复杂度显然可以是O(N2logN)

    级别

    我们可以换一种二分方式

    令当前左端点为L

    , 我们先找到一个最小的K, 使得[L,L+2K)这个区间混乱度超过M

    然后右端点在[L+2K1,L+2K)

    中二分即可

    考虑每删去至少2K1

    个数, 所需要的时间复杂度最大为O(2KKlogN)

    故总复杂度为O(Nlog2N)

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std ;
     4 
     5 int n ;
     6 
     7 typedef long long LL ; 
     8 
     9 LL M ; 
    10 
    11 const int MAXN = 300010 ;
    12 
    13 int a[MAXN] ; 
    14 
    15 int ps[MAXN], p[MAXN], cnt[MAXN], v[MAXN]; 
    16 bool vis[MAXN] ; 
    17 
    18 
    19 bool check(int l, int r) { 
    20         for (int i = l; i <= r; i ++) p[i] = a[i] ;  
    21         sort(p + l, p + r + 1) ; 
    22         LL ans = 0 ; 
    23         for (int i = l; i <= r; i ++) { 
    24                 ans += 1LL * p[i] * v[i - l + 1] ; 
    25         }
    26         return ans <= M ; 
    27 }
    28 
    29 int main() { 
    30         cin >> n >> M ; 
    31         for (int i = 1; i <= n; i ++) scanf("%d", &a[i]) ;
    32         for (int i = 1; i <= n; i ++) scanf("%d", &v[i]) ;     
    33         int l = 1, r = 1 ; 
    34         for (; l <= n;) { 
    35                  int last = 1, lastp = r - 1 ;  
    36                  for (; check(l, r) && lastp < r; lastp = r , r = min(n, r + last), last <<= 1) ; 
    37                  if (lastp == r) break ; 
    38                  int lp = lastp + 1, rp = r ; 
    39                  while (lp < rp) { 
    40                          int mid = ((lp + rp) >> 1) ; 
    41                          if (!check(l, mid)) rp = mid ;
    42                          else lp = mid + 1;  
    43                  }
    44                  cnt[lp] ++ ; 
    45                  l = lp + 1, r = l  ; 
    46         }
    47         for (int i = 1; i <= n; i ++) {
    48                 cnt[i] += cnt[i - 1] ; 
    49                 printf("%d", cnt[i]) ; 
    50                 if (i < n) putchar(' ') ; 
    51         }
    52         putchar(10) ; 
    53 }

    C

    题目链接:http://www.ifrog.cc/acm/problem/1113

    分析:

    注意到, K条路径两两相交的充要条件是这K

    条路径有一段公共路径。

    对于一条路径, 点数-边数恒为1

    所以我们可以算出所有可能的情况中, K

    条路径的公共点的个数 减去K

    条路径的公共边的条数, 即为答案

    我们可以枚举每一个点以及每一条边的贡献, 对于一个点来说, 它的贡献就是所有经过它的路径条数的K

    次方,边同理

    复杂度O(NlogK)

    , 瓶颈在于快速幂

     1 #include <bits/stdc++.h>
     2 
     3 #define MOD 1000000007
     4 
     5 #ifdef WIN32
     6 #define LLD "%I64d"
     7 #else
     8 #define LLD "%lld"
     9 #endif
    10 
    11 using namespace std ;
    12 
    13 int n, K ; 
    14 
    15 typedef long long LL ; 
    16 
    17 int qpow(int a, int b) { 
    18         int ret = 1 ;
    19         for (; b; b >>= 1, a = 1LL * a * a % MOD) if (b & 1) ret = 1LL * ret * a % MOD ; 
    20         return ret ;
    21 }
    22 
    23 const int MAXN = 500010 ; 
    24 
    25 int siz[MAXN], fa[MAXN];  
    26 
    27 vector<int> g[MAXN]; 
    28                 
    29 int main() { 
    30         scanf("%d%d", &n, &K) ; 
    31         for (int i = 2; i <= n; i ++) scanf("%d", &fa[i]) ; 
    32         for (int i = n; i; i --) {
    33                  siz[i] ++ ; 
    34                  siz[fa[i]] += siz[i] ; 
    35                  g[fa[i]].push_back(i) ; 
    36         }
    37         int ans = 0 ; 
    38         for (int i = 2; i <= n; i ++) { 
    39                 int t = 1LL * siz[i] * (n - siz[i]) % MOD ; 
    40                 ans = (ans - qpow(t, K) + MOD) % MOD ; 
    41         }
    42         for (int i = 1; i <= n; i ++) { 
    43                 int t = 0 ;
    44                 for (int j = 0; j < g[i].size(); j ++) { 
    45                         t += 1LL * siz[g[i][j]] * (n - siz[g[i][j]] - 1) % MOD ; 
    46                         t %= MOD ; 
    47                 }
    48                 t += 1LL * (siz[i] - 1) * (n - siz[i]) % MOD ; 
    49                 t %= MOD; 
    50                 t = 1LL * t * ((MOD + 1) / 2) % MOD ; 
    51                 t += n ; 
    52                 t %= MOD ; 
    53                 ans += qpow(t, K) ;
    54                 ans %= MOD ; 
    55         }
    56         printf("%d
    ", ans) ; 
    57 }    

    D

    题目链接:http://www.ifrog.cc/acm/problem/1114

    分析:

    SMN 为左边N个点, 右边M

    个点的完全二分图生成树个数

    答案即SKNK×(N1K1)

    , 证明显然, 因为把树上的点按照奇偶分层,即得到一个二分图, 每一棵树都对应了这个完全二分图的一个生成树

    SMN=NM1×MN1

    , 暴力用MatrixTree可以消元得到这个结论。

     1 #include <bits/stdc++.h>
     2 
     3 #define MOD 998244353
     4 
     5 using namespace std ;
     6 
     7 int n, k; 
     8 
     9 int qpow(int a, int b) { 
    10         int ret = 1; 
    11         for (; b; b >>= 1, a = 1LL * a * a % MOD) if (b & 1) ret = 1LL * ret * a % MOD ; 
    12         return ret ;
    13 }
    14 
    15 int C(int n, int m) { 
    16         int ans = 1 ; 
    17         for (int i = 1; i <= m; i ++) { 
    18                 ans = 1LL * ans * (n - i + 1) % MOD * qpow(i, MOD - 2) % MOD ; 
    19         }
    20         return ans ;
    21 }
    22                         
    23 int main() { 
    24 
    25         scanf("%d%d", &n, &k) ; 
    26         n -= k ; 
    27         int ans = 1LL * qpow(n, k - 1) * qpow(k, n - 1) % MOD ;
    28         ans = 1LL * ans * C(n + k - 1, k - 1) % MOD ; 
    29         printf("%d
    ", ans) ; 
    30 }

    E

    题目链接:http://www.ifrog.cc/acm/problem/1115

    分析:

      1 #define OPENSTACK
      2 
      3 #include <bits/stdc++.h>
      4 #define MAXN 100010
      5 #define Q 322
      6 #define INF ~0ULL
      7 
      8 using namespace std;
      9 
     10 int n , m , cnt , a[ MAXN ] , tag[ MAXN ] , caocoacao[ MAXN ] , up[ MAXN ] , vis[ MAXN ];
     11 int gandan [ MAXN ] , fa[ MAXN ] , size[ MAXN ] , son[ MAXN ] , xxxxxx[ MAXN ];
     12 unsigned char left_bit[65536] , ssssssss[65536];
     13 unsigned int wocaonimabis[31][ MAXN ] , f[31][65536] , lastans;
     14 
     15 struct wocaonima
     16 {
     17     unsigned long long bit[470];
     18     void clear()
     19     {
     20         memset( bit , 0 , sizeof( bit ) );
     21     }
     22     void operator |= ( const wocaonima & rhs )
     23     {
     24         for( register int i = 0 ; i <= 469 ; i++ )
     25             bit[i] |= rhs.bit[i];
     26     }
     27     void operator |= (const int x)
     28     {
     29         bit[x >> 6] |= 1ll << ( x & 63 );
     30     }
     31     inline int find( unsigned char k )
     32     {
     33         int len = 0 , v[4];
     34         register unsigned int x = 0;
     35         for( register int i = 0 ; i <= 469 ; i++ )
     36         {
     37             v[0] = bit[i] & 65535 , v[1] = ( bit[i] >> 16 ) & 65535 , v[2] = ( bit[i] >> 32 ) & 65535 , v[3] = ( bit[i] >> 48 );
     38             for( register char j = 0 ; j <= 3 ; j++ )
     39                 if( v[j] == 65535 ) len += 16;
     40                 else
     41                 {
     42                     //if( len + left_bit[ v[j] ] ) cerr << " " << len + left_bit[ v[j] ] << endl;
     43                     x += wocaonimabis[k][ len + left_bit[ v[j] ] ];
     44                     x += f[k][ v[j] ];
     45                     len = ssssssss[ v[j] ];
     46                 }
     47         }
     48         return x;
     49     }
     50 } ans;
     51 
     52 wocaonima BIT[Q + 5][Q + 5];
     53 vector < int > linker[ MAXN ];
     54 
     55 #define cur linker[x][i]
     56 
     57 void dfs1( int x )
     58 {
     59     size[x] = 1;
     60     for( int i = 0 ; i < linker[x].size() ; i++ )
     61         if( cur != fa[x] )
     62         {
     63             fa[ cur ] = x , gandan [ cur ] = gandan [x] + 1;
     64             dfs1( cur ) , size[x] += size[ cur ];
     65             if( size[ cur ] > size[ son[x] ] ) son[x] = cur;
     66         }
     67 }
     68 
     69 void dfs2( int x , int t )
     70 {
     71     xxxxxx[x] = t;
     72     if( son[x] ) dfs2( son[x] , t );
     73     for( int i = 0 ; i < linker[x].size() ; i++ )
     74         if( cur != fa[x] && cur != son[x] )
     75             dfs2( cur , cur );
     76 }
     77 
     78 inline int lca( int a , int b )
     79 {
     80     while( xxxxxx[a] != xxxxxx[b] )
     81     {
     82         if( gandan [ xxxxxx[a] ] < gandan [ xxxxxx[b] ] ) swap( a , b );
     83         a = fa[ xxxxxx[a] ];
     84     }
     85     return gandan [a] < gandan [b] ? a : b;
     86 }
     87 
     88 #undef cur
     89 
     90 struct io
     91 {
     92     char ibuf[1 << 23] , * s , obuf[1 << 20] , * t;
     93     int a[24];
     94     io() : t( obuf )
     95     {
     96         fread( s = ibuf , 1 , 1 << 23 , stdin );
     97     }
     98     ~io()
     99     {
    100         fwrite( obuf , 1 , t - obuf , stdout );
    101     }
    102     inline int read()
    103     {
    104         register int u = 0;
    105         while( * s < 48 ) s++;
    106         while( * s > 32 )
    107             u = u * 10 + * s++ - 48;
    108         return u;
    109     }
    110     template < class T >
    111     inline void print( T u , int v )
    112     {
    113         print( u );
    114         * t++ = v;
    115     }
    116     template< class T >
    117     inline void print( register T u )
    118     {
    119         static int * q = a;
    120         if( !u ) * t++ = 48;
    121         else
    122         {
    123             if( u < 0 )
    124                 * t++ = 45 , u *= -1;
    125             while( u ) * q++ = u % 10 + 48 , u /= 10;
    126             while( q != a )
    127                 * t++ = * --q;
    128         }
    129     }
    130 } ip;
    131 
    132 #define read ip.read
    133 #define print ip.print
    134 
    135 inline void addedge( int x , int y )
    136 {
    137     linker[x].push_back( y );
    138     linker[y].push_back( x );
    139 }
    140 
    141 int main()
    142 {
    143     #ifdef OPENSTACK
    144         int size = 64 << 20; // 64MB
    145         char *p = (char*)malloc(size) + size;
    146         #if (defined _WIN64) or (defined __unix)
    147             __asm__("movq %0, %%rsp
    " :: "r"(p));
    148         #else
    149             __asm__("movl %0, %%esp
    " :: "r"(p));
    150         #endif
    151     #endif
    152     srand( time( 0 ) );
    153     for( int s = 0 ; s < 65536 ; s++ )
    154     {
    155         left_bit[s] = ssssssss[s] = 16;
    156         for( register int i = 0 ; i < 16 ; i++ )
    157             if( !( ( s >> i ) & 1 ) )
    158             {
    159                 left_bit[s] = i;
    160                 break;
    161             }
    162         for( register int i = 15 ; ~i ; i-- )
    163             if( !( ( s >> i ) & 1 ) )
    164             {
    165                 ssssssss[s] = 15 - i;
    166                 break;
    167             }
    168     }
    169     n = read() , m = read();
    170     for( int i = 0 ; i <= n ; i++ )
    171         for( register int j = wocaonimabis[0][i] = 1 ; j <= 30 ; j++ )
    172             wocaonimabis[0][0] = 0 , wocaonimabis[j][i] = wocaonimabis[j - 1][i] * i;
    173     for( int j = 0 ; j <= 30 ; j++ )
    174         for( int s = 0 ; s < 65536 ; s++ )
    175         {
    176             int len = 0;
    177             for( register int i = left_bit[s] + 1 ; i <= 15 - ssssssss[s] ; i++ )
    178                 if( ( s >> i ) & 1 ) len++;
    179                 else f[j][s] += wocaonimabis[j][ len ] , len = 0;
    180             if( len ) f[j][s] += wocaonimabis[j][ len ];
    181         }
    182     for( register int i = 1 ; i <= n ; i++ ) a[i] = read();
    183     for( register int i = 1 ; i < n ; i++ ) addedge( read() , read() );
    184     dfs1( 1 ) , dfs2( 1 , 1 );
    185     for( int i = 1 ; i <= min( n , Q ) ; i++ )
    186     {
    187         int pos;
    188         while( vis[ pos = rand() * rand() % n + 1 ] );
    189         vis[ pos ] = 1 , tag[i] = pos , caocoacao[ tag[i] ] = i;
    190     }
    191     for( int i = 1 ; i <= min( n , Q ) ; i++ )
    192     {
    193         int cur = tag[i];
    194         ans.clear();
    195         do
    196         {
    197             ans |= a[ cur ];
    198             if( cur != tag[i] && caocoacao[cur] ) 
    199             {
    200                 BIT[i][ caocoacao[ cur ] ] |= ans;
    201                 if( !up[ tag[i] ] )
    202                     up[ tag[i] ] = cur;
    203             }
    204             cur = fa[ cur ];
    205         }
    206         while( cur );
    207     }
    208     for( int i = 1 ; i <= m ; i++ )
    209     {
    210         int cnt = read();
    211         ans.clear();
    212         for( int j = 1 ; j <= cnt ; j++ )
    213         {
    214             int x = read() ^ lastans , y = read() ^ lastans , z = lca( x , y );
    215             ans |= a[z];
    216             while( !caocoacao[x] && x != z )
    217             {
    218                 ans |= a[x];
    219                 x = fa[x];
    220             }
    221             int now = x;
    222             while( gandan [ up[x] ] > gandan [z] ) x = up[x];
    223             ans |= BIT[ caocoacao[ now ] ][ caocoacao[x] ];
    224             while( x != z )
    225             {
    226                 ans |= a[x];
    227                 x = fa[x];
    228             }
    229             while( !caocoacao[y] && y != z )
    230             {
    231                 ans |= a[y];
    232                 y = fa[y];
    233             }
    234             now = y;
    235             while( gandan [ up[y] ] > gandan [z] ) y = up[y];
    236             ans |= BIT[ caocoacao[ now ] ][ caocoacao[y] ];
    237             while( y != z )
    238             {
    239                 ans |= a[y];
    240                 y = fa[y];
    241             }
    242         }
    243         print( lastans = ans.find( read() ) , '
    ' );
    244     }
    245     #ifdef OPENSTACK
    246         exit(0);
    247     #else
    248         return 0;
    249     #endif
    250     return 0;
    251 }

  • 相关阅读:
    java入门 学习日志三 (面向对象1)
    java入门 学习日志二
    第八届蓝桥杯 b组试题解析
    java入门 学习日志一
    第九届蓝桥杯 b组 解析
    第九届蓝桥杯 b组 明码
    第十届蓝桥杯 b组
    包子凑数 、买不到的数目
    基础背包问题
    斐波那契数列第n项
  • 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/6669807.html
Copyright © 2011-2022 走看看