[UVA11076]Add Again
2015-10-09 10:39
399 查看
题目链接: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以内的阶乘,可以先跑一遍阶乘再把数据直接存入一个数组里备用。
代码如下:
题意:由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以内的阶乘,可以先跑一遍阶乘再把数据直接存入一个数组里备用。
代码如下:
#include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> using namespace std; typedef long long LL; const int maxn = 13; LL po[maxn] = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600}; int but[10]; int n; int num[maxn]; inline bool scan_d(int &num) { char in; bool ok = false; in = getchar(); if(in == EOF) { return false; } while(in != '-' && (in < '0' || in > '9')) { in = getchar(); } if(in == '-') { ok = true; num = 0; } else { num = in - '0'; } while(in = getchar(), in >= '0' && in <= '9') { num *= 10; num += in - '0'; } if(ok) { num = -num; } return true; } int main() { while(~scan_d(n) && n) { int flag = 0; LL sum = 0; memset(but, 0, sizeof(but)); for(int i = 0; i < n; i++) { scan_d(num[i]); sum += num[i]; but[num[i]]++; } LL poi = po ; for(int i = 0; i <= 9; i++) { if(but[i] == n) { flag = 1; break; } if(but[i] != 0) { poi /= po[but[i]]; } } if(flag) { for(int i = 0; i < n; i++) { printf("%d", num[0]); if(num[0] == 0) { break; } } printf("\n"); } else { LL ans = 0; sum = sum * poi / n; for(int i = 0; i < n; i++) { ans += sum; sum *= 10; } printf("%llu\n", ans); } } return 0; }
相关文章推荐
- JetBrains KegGen
- 人工智能●专家系统
- ORA-16025: parameter LOG_ARCHIVE_DEST_2 contains repeated or conflicting attributes
- redirect、redirect-action、chain三者的区别!
- RAID介绍、理解
- [LeetCode]18. Contains Duplicate II重复检测
- Failed to read key from keystore解决方案
- 基于WebDriver&TestNG 实现自己的Annotation @TakeScreenshotOnFailure
- 赋值运算符重载引发的思考(引用的功能) http://blog.csdn.net/yorkcai/article/details/8567441
- [DP]Codeforces Round #323 (Div. 2)DOnce Again...
- OS X系统U盘安装的问题
- LA 4394 String painter
- Leetcode | Climbing Stairs
- 【搜索】 HDU 4770 Lights Against Dudely
- BaiduMap SDK开发时只能显示网格不能显示地图的解决办法
- How To系列(二):how to baidu dork
- OpenStack Mnaila 2015-10-01 IRC会议内容
- POJ 3007:Organize Your Train part II
- POJ 3007:Organize Your Train part II
- http://blog.csdn.net/jackystudio/article/details/17019023