zoukankan      html  css  js  c++  java
  • [UVA11076]Add Again

    题目链接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=33478

    题意:由0~9中n个数字(可重复)组成的数组,把每个全排列看成一个n位数,求所有全排列的和。

    GF的方法:http://www.cnblogs.com/helenawang/p/4862782.html

    总感觉和她的有点儿不一样,嗯……跑了一下她的程序,23ms。为了证明我们家我说了算,给出如下更快的算法(6ms)

    高中学过的姿势,如果一个排列中有重复元素出现的话,那么它的排列数会按照一个规律减少:

    首先给出一个序列 a1 a2 a3 .... an

    我们把它的全排列写出来,发现它们每一位的数字出现的次数都是相同的,而且要求的和就是“重复出现次数*∑(1,n)ai”。可是不同的排列,这些数字出现的次数是不一样的,我想知道如何求出这个出现的次数。于是有了如下分析:

    1.如果这n个数没有任何重复,那么它的排列数为: n*(n-1)*(n-2)...1 = A(n,n) = n!,这是随意摆放的情况。

    2.如果这n个数有一组数重复了x次,那么按照高中老师讲过的排列组合,要相应去除掉对应个数的排列数。那么它的排列数为:A(n,n)/A(x,x),怎么样,是不是很眼熟?

    接下来推广到m组数据,分别重复x1 x2 .... xm次,我们很容易地得出一个结论,就是把这个排列数细分拆成如下形式:

    假设n个数字,分别重复了x1 x2 .....xn次(xi >= 1),那么这个排列的个数为:poi = A(n,n) / (A(x1,x1)*A(x2,x2)...A(xn,xn))

    因为数字是在[0,9]这个区间的,我们可以用一个桶来统计每一位出现的次数。这样,对于这个排列,每一位出现的次数也就统计了下来并且计算出poi。

    仔细观察可以知道,重复出现次数 = poi / n,这样,某一位的总和就能求出来了。接下来把所有位的和都求出来,那么模拟一下乘法搞一下就AC了。

    输入数据可以用getchar优化一下scanf,俗称输入挂。(它辅助我从19ms杀到了6ms)

    因为n<=12,用到了12以内的阶乘,可以先跑一遍阶乘再把数据直接存入一个数组里备用。

    代码如下:

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <iomanip>
     4 #include <cstring>
     5 #include <climits>
     6 #include <complex>
     7 #include <fstream>
     8 #include <cassert>
     9 #include <cstdio>
    10 #include <bitset>
    11 #include <vector>
    12 #include <deque>
    13 #include <queue>
    14 #include <stack>
    15 #include <ctime>
    16 #include <set>
    17 #include <map>
    18 #include <cmath>
    19 
    20 using namespace std;
    21 
    22 typedef long long LL;
    23 const int maxn = 13;
    24 LL po[maxn] = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600};
    25 int but[10];
    26 int n;
    27 int num[maxn];
    28 
    29 inline bool scan_d(int &num) {
    30     char in;
    31     bool ok = false;
    32     in = getchar();
    33     if(in == EOF) {
    34         return false;
    35     }
    36     while(in != '-' && (in < '0' || in > '9')) {
    37         in = getchar();
    38     }
    39     if(in == '-') { 
    40         ok = true;
    41         num = 0;
    42     }
    43     else {
    44         num = in - '0';
    45     }
    46     while(in = getchar(), in >= '0' && in <= '9') {
    47             num *= 10;
    48             num += in - '0';
    49     }
    50     if(ok) {
    51         num = -num;
    52     }
    53     return true;
    54 }
    55 
    56 int main() {
    57     while(~scan_d(n) && n) {
    58         int flag = 0;
    59         LL sum = 0;
    60         memset(but, 0, sizeof(but));
    61         for(int i = 0; i < n; i++) {
    62             scan_d(num[i]);
    63             sum += num[i];
    64             but[num[i]]++;
    65         }
    66         LL poi = po[n];
    67         for(int i = 0; i <= 9; i++) {
    68             if(but[i] == n) {
    69                 flag = 1;
    70                 break;
    71             }
    72             if(but[i] != 0) {
    73                 poi /= po[but[i]];
    74             }
    75         }
    76         if(flag) {            
    77             for(int i = 0; i < n; i++) {
    78                 printf("%d", num[0]);
    79                 if(num[0] == 0) {
    80                     break;
    81                 }
    82             }
    83             printf("
    ");
    84         }
    85         else {
    86             LL ans = 0;
    87             sum = sum * poi / n;
    88             for(int i = 0; i < n; i++) {
    89                 ans += sum;
    90                 sum *= 10;
    91             }
    92             printf("%llu
    ", ans);
    93         }
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    Leetcode 191.位1的个数 By Python
    反向传播的推导
    Leetcode 268.缺失数字 By Python
    Leetcode 326.3的幂 By Python
    Leetcode 28.实现strStr() By Python
    Leetcode 7.反转整数 By Python
    Leetcode 125.验证回文串 By Python
    Leetcode 1.两数之和 By Python
    Hdoj 1008.Elevator 题解
    TZOJ 车辆拥挤相互往里走
  • 原文地址:https://www.cnblogs.com/kirai/p/4863216.html
Copyright © 2011-2022 走看看