SGU 108 Self-numbers II

类型:递推,生成。

思路:看网上比较多的一种解法是根据定义进行筛选,用压缩数组进行优化。我的解法源自对大量数据的分析,刚开始只发现前后增加了11,然后发现比实际多出了很多数,准确的是多出的9999个,又编写程序查找出了几个新的增量。并进一步发现了新的规律。

解法:

从第六个self number开始,d[i] = d[i-1]+11, 即增加量是11;
每出现9个11,就会出现一个2;
每出现9个2,就会出现一个15;
每出现9个15,就会出现一个28;
每出现9个28,就会出现一个41;
每出现9个41,就会出现一个54;
...
(据推测,往后还会出现新的增量,在10^7内有这几个增量)
需要做的调整:跟2相邻的前后各有8个11,而不是9个;
跟15相邻的有7个,28有6个...

 

补:

东山同学发现了增量之间也有规律,除去11。

2,15,28,41,54形成等差数列,差值是13。

那么下一个增量就是67,经验证是正确的。

但是,新的问题是:每当新的增量出现,就要跟着调整11的个数,67前后有3个11。

直到有1个11,那么可能出现的情况是什么呢?会不会是又开始9个11?(有待验证)

代码
/*
46 ms 3879 kb
key: 因为没有及时跳出,导致求错总个数。
*/
#include
<stdio.h>
#include
<string.h>
#define NL 1000011

int d[NL];

int main()
{
int n, k, i, mj, t, t1, t2, t3, t4;
int kt[5001];
// freopen("in.txt", "r", stdin);
// freopen("all.txt", "w", stdout);
scanf("%d%d", &n, &k);
mj
= 0;
for (i=1; i<=k; i++) {
scanf(
"%d", &kt[i]);
if (kt[i] > mj) mj = kt[i];
}
d[
1] = 1;
d[
2] = 3;
d[
3] = 5;
d[
4] = 7;
d[
5] = 9;
t
= 1;
t1
= t2 = t3 = t4 = 0;

for (i=6; i<=n; i++) {
if (t == 10) {
t
= 1;
t1
++;
if (t1 == 9) {
if (t2 == 9) {
if (t3 == 9) {
if (t4 == 9) t++;
t
++;
}
t
++;
}
t
++;
}
if (t1 == 10) {
t1
= 0;
t2
++;
if (t2 == 10) {
t2
= 0;
t3
++;
if (t3 == 10) {
t3
= 0;
t4
++;
if (t4 == 10) {
t4
= 0;
d[i]
= d[i-1]+54;
if (d[i] > n) break; //key
t = 5;
continue;
}
d[i]
= d[i-1]+41;
if (d[i] > n) break; //key
t = 4;
continue;
}
d[i]
= d[i-1]+28;
if (d[i] > n) break; //key
t = 3;
continue;
}
d[i]
= d[i-1]+15;
if (d[i] > n) break; //key
t = 2;
continue;
}
d[i]
= d[i-1]+2;
if (d[i] > n) break; //key
continue;
}

d[i]
= d[i-1]+11;
t
++;
if (d[i] > n) break;
}
if (n < 10) printf("%d\n", (n+1)/2);
else printf("%d\n", i-1);
for (i=1; i<=k; i++) {
if (i!=1) putchar(' ');
printf(
"%d", d[kt[i]]);
}
printf(
"\n");
return 0;
}

 

posted @ 2010-08-09 17:24  superbin  阅读(492)  评论(0编辑  收藏  举报