ICPC2018Beijing 现场赛D Frog and Portal 构造

传送门

 

很有趣的一个构造题,跟队友训练的时候,一直在考虑,通过k传送到k,设置断点,然后各区间乘法原理,斐波那契数列取项求和,乘积之类的想法,并不对。

 

有些显然的结论。

总的方案数等于,到达199的方案数,加上到达198的方案数。但是我们通过k传送到k,可以构造出后面的方案数均为空。

从k传送到k,则总方案不会计入到达该层方案数。

从k传送到199,则总方案会计入一倍到达该层方案。

从k传送到k+1,则到达k+1层的方案会累加入到达k层的方案。

 

我们发现上面的三种构造,拥有0,1和+(相同时即为2倍),所以我们考虑将n二进制拆分。

 

比如n为7,拆分成1,2,4。

1传送到199 总方案数0+1=1 从1开始的方案数 1 1 1 2 3.....

3传送到4 从1开始的方案数1 1 1 2 2.....

5传送到199 总方案数1+2=3 从1开始的方案数 1 1 1 2 2 2 2 4...

7传送到8 从1开始的方案数 1 1 1 2 2 2 2 4 4...

9传送199 总方案数3+4=7 从1开始的方案数 1 1 1 2 2 2 2 4 4

10传送到10 从1开始的方案数 1 1 1 2 2 2 2 4 4 4 0 0 0 0....起到封死的效果

 

再比如n为5,拆分成1,4。

1传送到199 总方案数0+1=1 从1开始的方案数 1 1 1 2 3....

3传送到4 从1开始的方案数 1 1 1 2 2...

5传送到5 从1开始的方案数 1 1 1 2 2 2 2 4...

7传送到8 从1开始的方案数 1 1 1 2 2 2 2 4 4...

传送199 总方案数1+4=5 从1开始的方案数 1 1 1 2 2 2 2 4 4

10传送到10 从1开始的方案数 1 1 1 2 2 2 2 4 4 4 0 0 0 0....起到封死的效果

 

可以看到传送门很有规律,在奇数个奇数时,用来增加当前2的某次方,或者增加0。在偶数个技术时,用来把2的次方翻倍。最后用一个传送门封死。

 代码应该是对的,但是提交一直wa。试了些其他博客里的ac代码也都wa掉了。猜测评测机出锅。

 1 #include <cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 int ans,n;
 5 int main()
 6 {
 7     while (scanf("%lld",&n) > 0)
 8     {
 9         if (n == 0)
10         {
11             printf("2\n1 1\n2 1\n");
12             continue;
13         }
14         ans = 0;
15         for (int i = 31;i >= 0;i--)
16             if (n & (1ll << i))
17             {
18                 ans = i;
19                 break;
20             }
21         printf("%d\n",(ans + 1) * 2);
22         for (int i = 0;i <= ans;i++)
23         {
24             if (n & (1ll << i))
25                 printf("%d 199\n",i * 4 + 1);    
26             else
27                 printf("%d %d\n",i * 4 + 1,i * 4 + 1);
28             if (i != ans)
29                 printf("%d %d\n",i * 4 + 3,i * 4 + 4);
30             else
31                 printf("%d %d\n",i * 4 + 2,i * 4 + 2);
32         }
33     }
34     return 0;
35 }

 

posted @ 2019-10-06 19:51  IAT14  阅读(218)  评论(0编辑  收藏  举报