您的位置:首页 > 其它

挑战庞果英雄会之子序列的个数

2013-10-10 20:24 232 查看
题目详情

本题同样来自caopengcs,只要你有兴趣,每个人都可以出题(出题入口在主页右侧边栏“贡献题目”->“我要发布”内),以下是题目详情:

子序列的定义:对于一个序列a=a[1],a[2],......a
,则非空序列a'=a[p1],a[p2]......a[pm]为a的一个子序列,其中1<=p1<p2<.....<pm<=n。

例如:4,14,2,3和14,1,2,3都为4,13,14,1,2,3的子序列。

对于给出序列a,有些子序列可能是相同的,这里只算做1个,要求输出a的不同子序列的数量。

输入: 长度为n的数组1<=n<=100,数组元素0<=a[i]<=110

输出:子序列 的个数对1000000007取余数的结果(由于答案比较大,输出Mod 1000000007的结果即可)。

函数头部:

C/C++:

int run(cons int *a,int n);

其实我一开始就做对了,但是由于数目太大,超过了double能表示的精度,所以最后结果一直没有对。现在几经曲折,找到一种办法。来解决数目太大的问题。

先说算法的思想,从左到右添加子序列,第一次取最左边的一个,第二次,加入第二个,第三次加入第三个‘’‘’‘’‘’加很简单,主要是要去除相同的元素。

我用一个数组来记录加入一个数后当前序列个数增加的数目。既这些数目是由于加了这个数才产生的。

假设当前添加到第i个数,前面有N个不相同的子序列,那么新加了这个数后,子序列的长度会增加一倍再加1,但是其中包含了很多重复的序列,重复的序列是因为前面存在相同的数字,只要用前面子序列的长度减去这些重复的数目,得到的就是这个新添加的数产生的新的子序列数目,记做in。假设前面只要第K个数和这个i上面的数相等,那么in = N +1 - kn;如果前面还有其它相等的数,同样要减去那个位置记录的数。最后子序列的总数目等于 i1 + i2 + *+
in;

这样思想是对的,但是要实现还差一点,因为最后的子序列数目非常大,用int不能表示,用long long也不能表示。

用double类型是能够有这个范围,但是失去了精度,不能保存个位十位百位这些低位的数。我想到可以将结果分开来存,到结果大于一个数后,就将大于的部分另外存储。但是这样运算速度太慢,失败!后来我发现其实只需要存储小于1000000007的部分就可以了,因为大于的部分最后求余的时候都是没有用的,而且运算中只要加减运算,于是结果如下:

int run(const int *a,int n) {

int iNum = 0;

int iArry[100];

for (int i = 0; i < n; i++)

{

iArry[i] = iNum + 1;

for (int j = 0; j < i; j++)

{

if (a[i] == a[j])

{

iArry[i] -= iArry[j];

if (iArry[i] < 0)

{

iArry[i] += 1000000007;

}

}

}

iNum += iArry[i];

if (iNum > 1000000007)

{

iNum -= 1000000007;

}

}

return iNum;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: