不可思议唤来不可思议β
Time Limit: 1 Sec Memory Limit: 128 MB
Description
In the world line 1.048596%
双叶理央因为“青春期症候群”,分裂成为了两个人。由于被“冒牌货”顶替,“真正”的双叶理央只能借住在梓川咲太的家里。
“假设现在有一个设计图记录了一个人的所有信息,又因为量子隐形传态的原因在别的地方也出现了这样的设计图,那么就相当于存在了两个我。”
“但这毕竟不是理论能解释的事情,如果真的是量子隐形传态,那么我在行为的同时,也会影响另一个我。可现实并不是这样。”
“虽然很不想承认‘青春期症候群’的存在,不过如今也不得不承认了。”
“明明以前就那么不想承认?”梓川咲太坐在浴室的门前回应。
“实际上我还是不承认,这种非理性的事情。”,双叶理央叹了口气。
“双叶老师,其实前面我一句话都没听懂。”感觉到话题继续发展下去非常尴尬,梓川咲太开始自爆。
“没办法,抛开量子力学,用你这种笨蛋也能懂的话来说明吧。现在把人的所有特征信息简化为n个数字(0~9),那么自由组合成所有可能的n位数(包含前导零),然后这些数字再累加起来。这样的和就能代表那个人。”
“你就算这样说我也不是很懂啊…”
"假设梓川你的特征能简化为3个数字<0,1,2>,那么就能组成6个无视前导零的3位数,分别是012,021,102,120,210,201,这些数字加起来的和是666,那么666就能代表你这个人,kukuku,恶魔的数字,还真是不幸啊。”
“现在的我什么都不能反驳呢。”梓川不自觉的摸了摸胸前的伤痕。
然后,当晚被迫睡客厅的好男人梓川咲太总是睡不着。他一直在想如何快速的算出那个和。人脑始终是有极限的,那么只能求助于现代科技了。
Input
多组样例,每组输入包括两行;
第一行一个整数 n ,表示有n个数。(n<=10)
第二行包括 n 个整数x。(0 <= x <= 9)
当输入的 n 为 0 时结束输入(结束程序)
保证每组数据样例不超过50000个, 同时保证最后的答案不会超过2^63-1
Output
每组样例输出一行
每行一个数字,表示题目中要求的和
Sample Input
3 1 2 3 3 1 1 2 0
Sample Output
1332 444
问题分析:
不得不说这道题目我又陷入思维定势了,看到全排列,一想到的就是DFS,但DFS算法实际上展示出来的不是完整的一个个数,而是一个个单独的数位的拼接。再加上题目又要求要将这些数字相加,还要无视前导0,其实这两个条件用DFS算法稍微修改为加法还是可以解决的。但有一个很致命的问题就是,如何去除数据中重复计算的部分,我死活就想不出来用DFS这个要怎么解决这个问题。
想了许久无果后只能求助于论坛了,发现只有仅仅的一篇博客有讲解这道题目,看来是师兄了,看完之后如雷贯耳!很巧妙的用高中知识就解决了重复计算的问题,用排列组合的知识代替了DFS算法,这里我将师兄的博文内容复制过来给大家看看
排列组合题,显然枚举会超时。比赛时思路是对的,但是忘了含有重复元素的排列数怎么算,使劲推公式,没有思路,无果,,回来一查,这不是高中数学排列组合裸题吗!
假设有 111223这6个数,如何计算它的全排列呢?先假设这6个数字都不相同,排列共A(6,6)种,但在这A(6,6)种排列中,3个1和2个2是一样的,但被计算了A(3,3),A(2,2)种,因此答案就是A(6,6)/A(3,3)/A(2,2)种,这就是这道题最关键的地方。
先考虑最左边那一位可以填1,2,3三种,可以确定全排列中最高位分别为1,2,3时排列的个数,设排列总数为x,则最高位的数字可以确定加起来等于x105,其实全排列先考虑哪一个位都是一样的,其他每一位都可以这样考虑,结果就是x*105+x104+x*103+x10^2+x10+x.
这个x又怎么确定呢?当填1时排列数为1*(11223的全排列数),填2时排列数为2*(11123的全排列数),填3时排列数为3*(11122的全排列数),就是这样的思路。
下来写时候一处从0开始脑抽写出1开始,找不出错,然后花好多时间和next_permutation对拍才找出来错误。
不得不感慨,数学nb!师兄nb!
然后自己再写的时候,写完自己的代码再看师兄的代码,简直自愧不如,自己的代码质量太差了,太冗长了,可读性极差,师兄的代码真的超级精简,感觉像是一个艺术品!
强烈推荐大家看看师兄的其他博客!
AC代码:
#include <bits/stdc++.h>
using namespace std;
int a[10];
int num[10];
//一开始闲的没事干还想用函数 多此一举
//int A(int n)
//{
// if ( a[n] )
// return a[n];
// else
// return a[n]=n*A(n-1);
//}
int main()
{
int i,j;
int t;
while(1)
{
int n;
cin >> n;
if ( n==0 )
break;
long long ans=0;
int type=0;
long long sum=0;
memset(num,0,sizeof(num));
for ( i=0; i<n; ++i )
{
cin >> t;
num[t]++;
}
a[0] = a[1] = 1;
for ( i=2; i<=10; ++i )
a[i] = i*a[i-1];
for ( i=0; i<10; ++i )
if ( num[i] )
{
sum = i*a[n-1];
for ( j=0; j<10; ++j )
if ( i==j )
sum /= a[num[j]-1];
else
sum /= a[num[j]];
type += sum;
}
for ( i=1; i<=n; ++i )
ans = ans*10 + type;
cout << ans << endl;
}
}