• USACO 3.2


    3.2开始是背包的介绍,然后六个题目,没有一题和背包有关系!

    Factorials:比较经典的一个题。求n阶乘最右边第一个不为0的数字。因为0肯定是有一个因子2和一个因子5组合成的,而在n!中因数2的个数显然远多于5的个数。所以for一遍n,碰到因数2就加1,碰到因数5就减1。剩下的乘起来对10取mod,最后再乘一下剩下的2的个数。

     1 # include <stdio.h>
     2 
     3 
     4 int main ()
     5 {
     6     int n, ans, i, two, ii ;
     7     freopen ("fact4.in", "r", stdin) ;
     8     freopen ("fact4.out", "w", stdout) ;
     9     while (~scanf ("%d", &n))
    10     {
    11         ans = 1 ;
    12         two = 0 ;
    13         for (i = 1 ; i <= n ; i++)
    14         {
    15             ii = i ;
    16             while (ii%2 == 0) ii/=2, two++ ;
    17             while (ii%5 == 0) ii/=5, two-- ;
    18             ans = (ans*ii)%10 ;
    19         }
    20         while (two--) ans = (ans*2)%10 ;
    21         printf("%d
    ", ans) ;
    22     }
    23     return 0 ;
    24 }
    View Code

    Stringsobits:递推加递归。递推算出对于所有的n和l,不超过l个1长度为n的字符串有几个。f[n,l] = f[n-1,l]+f[n-1,l-1]。边界要特别注意:f[n,0] = 1。之后递归,根据长度为n开头为0且1的个数不超过L的字符串个数可以确定第一位是0还是1。

     1 # include <stdio.h>
     2 # include <string.h>
     3 
     4 
     5 int tab[40][40] ;
     6 
     7 
     8 int recv(int n, int l)
     9 {
    10     if (l == 0) return 1 ;
    11     if (l > n) return recv (n,n) ;
    12     if (tab[n][l] != -1) return tab[n][l] ;
    13     return tab[n][l] = (recv(n-1,l)+recv(n-1,l-1)) ;
    14 }
    15 
    16 
    17 int main ()
    18 {
    19     long long n, l, I, i ;
    20     freopen ("kimbits.in", "r", stdin) ;
    21     freopen ("kimbits.out", "w", stdout) ;
    22     memset (tab, -1, sizeof(tab)) ;
    23     tab[0][0] = 1 ;
    24     while (~scanf ("%lld%lld%lld", &n, &l, &I))
    25     {
    26         for (i = n ; i > 0 ; i--)
    27         {
    28             n = i ;
    29             if (I <= recv(n-1,l))
    30                 printf ("0") ;
    31             else{
    32                 printf ("1") ;
    33                 I -= recv(n-1,l) ;
    34                 l-- ;
    35             }
    36         }
    37         puts ("") ;
    38     }
    39     return 0 ;
    40 }
    View Code

    Spinning Wheels:这题主要题意细节比较多,其他没啥。把时间从0到359枚举一次,因为超过这个时间肯定陷入周期。注意细节就可以了。

     1 # include <stdio.h>
     2 
     3 
     4 typedef struct WHEEL{
     5     int angle[360] ;
     6     int speed ;
     7     
     8 }WHEEL ;
     9 
    10 
    11 WHEEL wheel[5] ;
    12 int buff[360] ;
    13 
    14 
    15 void Input(WHEEL* p)
    16 {
    17     int i, a, b, num ;
    18     for (i = 0 ; i < 360 ; i++)
    19         p->angle[i] = 0 ;
    20     scanf ("%d", &p->speed) ;
    21     scanf ("%d", &num) ;
    22     while (num--)
    23     {
    24         scanf ("%d%d", &a, &b) ;
    25         for (i = a ; i <= a+b ; i++)
    26             p->angle[i%360] = 1 ;
    27     }
    28 }
    29 
    30 
    31 void Move(WHEEL* p)
    32 {
    33     int i ;
    34     for (i = 0 ; i < 360 ; i++)
    35         buff[i] = p->angle[i] ;
    36     for (i = 0 ; i < 360 ; i++)
    37         p->angle[i] = buff[(i-p->speed+360)%360] ;
    38 }
    39 
    40 
    41 int Judge()
    42 {
    43     int i, j ;
    44     for (i = 0 ; i < 360 ; i++)
    45     {
    46         for (j = 0 ; j < 5 ; j++)
    47             if (wheel[j].angle[i] == 0) break ;
    48         if (j >= 5) return 1 ;
    49     }
    50     return 0 ;
    51 }
    52 
    53 
    54 int gao()
    55 {
    56     int i, j ;
    57     for (i = 0 ; i < 360 ; i++)
    58     {
    59         if (Judge()) return i ;
    60         for (j = 0 ; j < 5 ; j++)
    61             Move(&wheel[j]) ;
    62     }
    63     return -1 ;
    64 }
    65 
    66 
    67 int main ()
    68 {
    69     int i, ans ;
    70     freopen ("spin.in", "r", stdin) ;
    71     freopen ("spin.out", "w", stdout) ;
    72     for (i = 0 ; i < 5 ; i++)
    73         Input(&wheel[i]) ;
    74     ans = gao() ;
    75     if (ans == -1) printf ("none
    ") ;
    76     else printf ("%d
    ", ans) ;
    77     return 0 ;
    78 }
    View Code

    Feed Ratios:一开始没注意答案不会超过100这个条件。看到以后就知道是一个O(n^3)的暴力算法。同样是要注意细节,每次除法除数都要判断是否为0。

     1 # include <stdio.h>
     2 
     3 
     4 int judge (int a, int b)
     5 {
     6     if (b == 0 && a == 0) return 101 ;
     7     if (b == 0) return -1 ;
     8     if (a % b != 0) return -1 ;
     9     return a/b ;
    10 }
    11 
    12 
    13 int min(int a, int b){return a<b?a:b;}
    14 
    15 
    16 int main ()
    17 {
    18     int i, j, k, kk ;
    19     int a, b, c, ka, kb, kc, a1, a2, a3, a4 ;
    20     int x[4][3] ;
    21     freopen ("ratios.in", "r", stdin) ;
    22     freopen ("ratios.out", "w", stdout) ;
    23     for (i = 0 ; i < 4 ; i++)
    24         for (j = 0 ; j < 3 ; j++)
    25             scanf ("%d", &x[i][j]) ;
    26     a4 = 1000 ;
    27     for (i = 0 ; i <= 100 ; i++)
    28         for (j = 0 ; j <= 100 ; j++)
    29             for (k = 0 ; k <= 100 ; k++)
    30             {
    31                 if (i == 0 && j == 0 && k == 0) continue ;
    32                 a = i * x[1][0] + j * x[2][0] + k * x[3][0] ;
    33                 b = i * x[1][1] + j * x[2][1] + k * x[3][1] ;
    34                 c = i * x[1][2] + j * x[2][2] + k * x[3][2] ;
    35                 if (b * x[0][0] != a * x[0][1]) continue ;
    36                 if (c * x[0][0] != a * x[0][2]) continue ;
    37                 ka = judge(a, x[0][0]) ;
    38                 if (ka < 0) continue ;
    39                 kb = judge(b, x[0][1]) ;
    40                 if (kb < 0) continue ;
    41                 kc = judge(c, x[0][2]) ;
    42                 if (kc < 0) continue ;
    43                 if (ka > 100 && kb > 100 && kc > 100) continue ;
    44                 kk = min(ka, min(kb, kc)) ;
    45                 if (ka > 100) ka = kk ;
    46                 if (ka != kk) continue ;
    47                 if (kb > 100) kb = kk ;
    48                 if (kb != kk) continue ;
    49                 if (kc > 100) kc = kk ;
    50                 if (kc != kk) continue ;
    51                 if (kk < a4) a1 = i, a2 = j, a3 = k, a4 = kk ;
    52             }
    53     if (a4 > 100) puts ("NONE") ;
    54     else printf ("%d %d %d %d
    ", a1,a2,a3,a4) ;
    55     return 0 ;
    56 }
    View Code

    Magic Squares:标准BFS解,没啥好说的。值得一提的是hash的时候,可以像我这样直接拿拼出来的数字取mod,也可以用最完美的逆序数哈希算法。这题的代码稍加变形就可以拿来A八数码问题。

      1 # include <stdio.h>
      2 # include <string.h>
      3 
      4 
      5 # define HASH_MAX 50021
      6 
      7 
      8 int hash[HASH_MAX+10] ;
      9 int a[8], start, end ;
     10 int q[HASH_MAX+10], fa[HASH_MAX+10], step[HASH_MAX+10] ;
     11 char path[HASH_MAX+10] ;
     12 char tab[] = "ABC" ;
     13 
     14 
     15 int A(int x)
     16 {
     17     int i, t ;
     18     for (i = 7 ; i >= 0 ; i--)
     19         a[i] = x%10, x /= 10 ;
     20     for (i = 0 ; i < 4 ; i++)
     21         t = a[i], a[i] = a[7-i], a[7-i] = t ;
     22     for (i = 0, x = 0 ; i < 8 ; i++)
     23         x = x * 10 + a[i] ;
     24     return x ;
     25 }
     26 
     27 int B(int x)
     28 {
     29     int i, t ;
     30     for (i = 7 ; i >= 0 ; i--)
     31         a[i] = x%10, x /= 10 ;
     32     t = a[3], a[3] = a[2], a[2] = a[1], a[1] = a[0], a[0] = t ;
     33     t = a[4], a[4] = a[5], a[5] = a[6], a[6] = a[7], a[7] = t ;
     34     for (i = 0, x = 0 ; i < 8 ; i++)
     35         x = x * 10 + a[i] ;
     36     return x ;
     37 }
     38 
     39 
     40 int C(int x)
     41 {
     42     int i, t ;
     43     for (i = 7 ; i >= 0 ; i--)
     44         a[i] = x%10, x /= 10 ;
     45     t = a[2], a[2] = a[1], a[1] = a[6], a[6] = a[5], a[5] = t ;
     46     for (i = 0, x = 0 ; i < 8 ; i++)
     47         x = x * 10 + a[i] ;
     48     return x ;
     49 }
     50 
     51 
     52 int hashash(int x)
     53 {
     54     int i ;
     55     for (i = x % HASH_MAX ; hash[i] != 0; i=(i+1)%HASH_MAX)
     56         if (hash[i] == x) return 1 ;
     57     return 0 ;
     58 }
     59 
     60 
     61 void Hash(int x)
     62 {
     63     int i ;
     64     for (i = x % HASH_MAX ; hash[i] != 0 ; i = (i+1)%HASH_MAX) ;
     65     hash[i] = x ;
     66 }
     67 
     68 
     69 int bfs ()
     70 {
     71     int i, front = 0, rear = 1, x, xx ;
     72     int (*fun[3])(int) = {A, B, C} ;
     73     q[0] = start ;
     74     Hash(start) ;
     75     step[0] = 0 ;
     76     while (front != rear)
     77     {
     78         x = q[front++] ;
     79         if (x == end) return front-1 ;
     80         for (i = 0 ; i < 3 ; i++)
     81         {
     82             xx = (*fun[i])(x) ;
     83             if (!hashash(xx))
     84             {
     85                 Hash(xx) ;
     86                 path[rear] = tab[i] ;
     87                 fa[rear] = front-1 ;
     88                 step[rear] = step[front-1] + 1 ;
     89                 q[rear++] = xx ;
     90             }
     91         }
     92     }
     93 }
     94 
     95 
     96 void PrtPath(int idx){
     97     if (idx == 0) return ;
     98     PrtPath(fa[idx]) ;
     99     printf ("%c", path[idx]) ;
    100 }
    101 
    102 
    103 int main ()
    104 {
    105     int i, idx ;
    106     freopen ("msquare.in", "r", stdin) ;
    107     freopen ("msquare.out", "w", stdout) ;
    108     while (~scanf ("%d %d %d %d %d %d %d %d", 
    109                     &a[0], &a[1], &a[2], &a[3],
    110                     &a[4], &a[5], &a[6], &a[7]))
    111     {
    112         memset (hash, 0, sizeof(hash)) ;
    113         end = 0 ;
    114         for (i = 0 ;i < 8 ; i++) end = end*10+a[i] ;
    115         start = 12345678 ;
    116         idx = bfs () ;
    117         printf ("%d
    ", step[idx]) ;
    118         PrtPath(idx) ;
    119         printf ("
    ") ;
    120     }
    121     return 0 ;
    122 }
    View Code

    Sweet Butter:很容易想到枚举每个点作为“中点”,剩下的问题就是单源最短路径问题。值得注意的是点的个数是800,边数是1450,是一个很稀疏的图,可以用Dijstra+堆优化(O((V+E)lgV))或者SPFA算法。这里用的是Dijkstra+堆优化的方法过的。本题是这章里面代码量最大的。某些小朋友偷懒不好好写堆,用STL的优先队列来写,也是可以的- -。

      1 # include <stdio.h>
      2 # include <stdlib.h>
      3 # include <string.h>
      4 
      5 
      6 typedef struct EDGE{
      7     int s, e, w ;
      8 }EDGE ;
      9 
     10 
     11 typedef struct VERTEX{
     12     int idx, dist ;
     13 }VERTEX ;
     14 
     15 
     16 EDGE edge[3100] ;
     17 int vidx[810], vnum[810], num[810] ;
     18 int INF = 0x3f3f3f3f ;
     19 
     20 
     21 int dist[810], vis[810], inheap[810] ;
     22 VERTEX heap[810] ;
     23 int heap_len ;
     24 
     25 
     26 void heapify(int idx)
     27 {
     28     VERTEX tmp ;
     29     int lidx = idx ;
     30     if (idx*2 <= heap_len && heap[idx*2].dist < heap[lidx].dist)
     31         lidx = idx*2 ;
     32     if (idx*2+1 <= heap_len && heap[idx*2+1].dist < heap[lidx].dist)
     33         lidx = idx*2+1 ;
     34     
     35     if (lidx != idx){
     36         inheap[heap[idx].idx] = lidx ;
     37         inheap[heap[lidx].idx] = idx ;
     38         tmp = heap[idx], heap[idx] = heap[lidx], heap[lidx] = tmp ;
     39         heapify (lidx) ;
     40     }
     41 }
     42 
     43 
     44 VERTEX pop()
     45 {
     46     VERTEX rtn = heap[1] ;
     47     heap[1] = heap[heap_len--] ;
     48     if (heap_len)
     49     {
     50         inheap[heap[1].idx] = 1 ;
     51         heapify(1) ;
     52     }
     53     return rtn ;
     54 }
     55 
     56 
     57 void update (int vidx, int d)
     58 {
     59     VERTEX tmp ;
     60     int i ;
     61     if (inheap[vidx] == 0)
     62         heap[heap_len+1].idx = vidx, heap[heap_len+1].dist = d, 
     63         inheap[vidx] = heap_len+1, heap_len++ ;
     64     else heap[inheap[vidx]].dist = d ;
     65     
     66     for (i = inheap[vidx] ; i != 1 ; i /= 2)
     67     {
     68         if (heap[i/2].dist > heap[i].dist)
     69         {
     70             inheap[heap[i/2].idx] = i ;
     71             inheap[heap[i].idx] = i/2 ;
     72             tmp = heap[i/2], heap[i/2] = heap[i], heap[i] = tmp ;
     73         }
     74         else break ;
     75     }
     76 }
     77 
     78 
     79 void dijkstra(int sv, int n)
     80 {
     81     VERTEX v ;
     82     int i, ii;
     83     memset (vis, 0, sizeof(vis)) ;
     84     memset (dist, 0x3f, sizeof(dist)) ;
     85     memset (inheap, 0, sizeof(inheap)) ;
     86     heap[1].idx = sv, heap[1].dist = 0, inheap[sv] = 1, heap_len = 1 ;
     87     for (ii = 1 ; ii < n ; ii++)
     88     {
     89         v = pop() ;
     90         dist[v.idx] = v.dist ;
     91         vis[v.idx] = 1 ;
     92         for (i = 0 ; i < vnum[v.idx] ; i++) if (vis[edge[vidx[v.idx]+i].e] == 0)
     93             if (edge[vidx[v.idx]+i].w + v.dist < dist[edge[vidx[v.idx]+i].e])
     94             {
     95                 dist[edge[vidx[v.idx]+i].e] = edge[vidx[v.idx]+i].w + v.dist ;
     96                 update (edge[vidx[v.idx]+i].e, dist[edge[vidx[v.idx]+i].e]) ;
     97             }
     98     }
     99 }
    100 
    101 
    102 int gao(int sv, int n)
    103 {
    104     int i, ans = 0 ;
    105     dijkstra(sv, n) ;
    106     for (i = 1 ; i <= n ; i++)
    107         ans += (num[i] * dist[i]) ;
    108     return ans ;
    109 }
    110 
    111 
    112 int min(int a, int b){return a<b?a:b;}
    113 
    114 
    115 int cmp(const void *a, const void *b)
    116 {
    117     EDGE *p = (EDGE*)a, *q = (EDGE*)b ;
    118     if (p->s != q->s) return p->s - q->s ;
    119     if (p->e != q->e) return p->e - q->e ;
    120     return p->w - q->w ;
    121 }
    122 
    123 
    124 int main ()
    125 {
    126     int n, p, c, ans, x ;
    127     int i, s, e, w ;
    128     freopen ("butter.in", "r", stdin) ;
    129     freopen ("butter.out", "w", stdout) ;
    130     while (~scanf ("%d%d%d", &n, &p, &c))
    131     {
    132         memset (num,0,sizeof(num)) ;
    133         while (n--)
    134             scanf ("%d", &x), num[x]++ ;
    135         for (i = 0 ;i < c ; i++)
    136         {
    137             scanf ("%d%d%d", &s, &e, &w) ;
    138             edge[2*i].s = s, edge[2*i].e = e, edge[2*i].w = w ;
    139             edge[2*i+1].s = e, edge[2*i+1].e = s, edge[2*i+1].w = w ;
    140         }
    141         qsort(edge, 2*c, sizeof(edge[0]), cmp) ;
    142         memset (vnum, 0, sizeof(vnum)) ;
    143         memset (vidx, -1, sizeof(vidx)) ;
    144         for (i = 0 ; i < 2*c ; i++)
    145         {
    146             vnum[edge[i].s]++ ;
    147             if (vidx[edge[i].s] == -1) vidx[edge[i].s] = i ;
    148         }
    149         ans = INF ;
    150         for (i = 1 ; i <= p ; i++)
    151             ans = min(ans, gao(i, p)) ;
    152         printf ("%d
    ", ans) ;
    153     }
    154     return 0 ;
    155 }
    View Code

     UP:用SPFA实现了一个,时间上比Dijstra要快上一些。而且SPFA好写啊!

      1 # include <stdio.h>
      2  # include <stdlib.h>
      3  # include <string.h>
      4  
      5  
      6  typedef struct EDGE{
      7      int s, e, w ;
      8  }EDGE ;
      9  
     10  
     11  typedef struct VERTEX{
     12      int idx, dist ;
     13  }VERTEX ;
     14  
     15  
     16  EDGE edge[3100] ;
     17  int vidx[810], vnum[810], num[810] ;
     18  int INF = 0x3f3f3f3f ;
     19  
     20  
     21  int dist[810], inqueue[810], q[6000] ;
     22  
     23  
     24  void spfa(int sv, int n)
     25  {
     26      int f, r, v, vv, i ;
     27      memset (dist, 0x3f, sizeof(dist)) ;
     28      memset (inqueue, 0, sizeof(inqueue)) ;
     29      dist[sv] = 0, q[3000] = sv, inqueue[sv] = 1 ;
     30      for (f = 3000, r = 3001 ; f < r ; f++)
     31      {
     32          v = q[f] ;
     33          inqueue[v] = 0 ;
     34          for (i = vidx[v] ; i < vidx[v]+vnum[v] ; i++)
     35          {
     36              vv = edge[i].e ;
     37              if (dist[vv] > dist[v]+edge[i].w)
     38              {
     39                  dist[vv] = dist[v]+edge[i].w ;
     40                  if (inqueue[vv] == 0)
     41                  {
     42                      inqueue[vv] = 1 ;
     43                      if (dist[vv] < dist[q[f]])
     44                          q[--f] = vv ;
     45                      else q[r++] = vv ;
     46                  }
     47              }
     48          }
     49      }
     50  }
     51  
     52  
     53  int gao(int sv, int n)
     54  {
     55      int i, ans = 0 ;
     56      spfa(sv, n) ;
     57      for (i = 1 ; i <= n ; i++)
     58          ans += (num[i] * dist[i]) ;
     59      return ans ;
     60  }
     61  
     62  
     63  int min(int a, int b){return a<b?a:b;}
     64  
     65  
     66  int cmp(const void *a, const void *b)
     67  {
     68      EDGE *p = (EDGE*)a, *q = (EDGE*)b ;
     69      if (p->s != q->s) return p->s - q->s ;
     70      if (p->e != q->e) return p->e - q->e ;
     71      return p->w - q->w ;
     72  }
     73  
     74  
     75  int main ()
     76  {
     77      int n, p, c, ans, x ;
     78      int i, s, e, w ;
     79      freopen ("butter.in", "r", stdin) ;
     80      freopen ("butter.out", "w", stdout) ;
     81      while (~scanf ("%d%d%d", &n, &p, &c))
     82      {
     83          memset (num,0,sizeof(num)) ;
     84          while (n--)
     85              scanf ("%d", &x), num[x]++ ;
     86          for (i = 0 ;i < c ; i++)
     87          {
     88              scanf ("%d%d%d", &s, &e, &w) ;
     89              edge[2*i].s = s, edge[2*i].e = e, edge[2*i].w = w ;
     90              edge[2*i+1].s = e, edge[2*i+1].e = s, edge[2*i+1].w = w ;
     91          }
     92          qsort(edge, 2*c, sizeof(edge[0]), cmp) ;
     93          memset (vnum, 0, sizeof(vnum)) ;
     94          memset (vidx, -1, sizeof(vidx)) ;
     95          for (i = 0 ; i < 2*c ; i++)
     96          {
     97              vnum[edge[i].s]++ ;
     98              if (vidx[edge[i].s] == -1) vidx[edge[i].s] = i ;
     99          }
    100          ans = INF ;
    101          for (i = 1 ; i <= p ; i++)
    102              ans = min(ans, gao(i, p)) ;
    103          printf ("%d
    ", ans) ;
    104      }
    105      return 0 ;
    106  }
    View Code
  • 相关阅读:
    转:中国菜刀用法
    转的:burp suite小例子
    [转]阿里前员工评马云
    Burp Suite使用教程
    C++实现按绩点排名
    C++排列对称串
    C++实现01串排序
    C++判断五位以内的对称素数
    C++12!配对
    C++列出完数
  • 原文地址:https://www.cnblogs.com/lzsz1212/p/3173737.html
Copyright © 2020-2023  润新知