您的位置:首页 > 其它

2017.3.6 地精部落 思考记录

2017-03-06 08:09 190 查看
        其实这个题第一眼是没有任何思路的

        强行无视题解,经过漫长的找规律,终于推出了一个可行的方法:

        f[i][0/1]i表示最高位的数字,0表示开始是上升,1表示开始是下降。

            为什么会推出这个?

        1、因为所谓抖动序列和每个数的具体值没有关系,只与它的大小有关系,

        2、在下一个循环中,枚举开头数字,所以只和上一种情况的最高位有关,在数位依次递增的时候循环开头的每个情况即可。

   例:        若为1、 2、 3、 4、 5:

                 开始是2,    后面是1、 3、 4、 5,分别对应4个数时的1 、2、 3、 4;

                            转移条件即为上一次递推 <2 上升 作为最高位为 2 的下降方案数

                                                    上一次递推 >=2 下降 作为最高位为 2 的上升方案数

                 

         这真是极好的,但是n^3时间爆炸、 

但作为省选题,50的得分还是可以的、

       看来这种数类问题最好还是先把表列出来分析,不然空想实在不行,

      而且这种问题好像都是插数递推+一定的枚举、

        20天后:

       woc这么明显的前缀和+后缀和优化都看不出来?就这么弃了太可惜、、

           20分钟码完和优化版,成功ac;;

     ps:正解依然有点懵逼、有空再看吧

码:

#include<iostream>
#include<cstdio>
using namespace std;
int n,p,dowh,ans,i,f[2][5000][2],j;
int main()
{
scanf("%d%d",&n,&p);
dowh=1;
f[0][1][0]=1;
f[0][1][1]=1;
f[0][2][1]=1;
f[0][2][0]=1;
for(i=3;i<=n;i++,dowh^=1)
{
for(j=1;j<=i;j++)
f[dowh][j][0]=f[dowh^1][j][1];
for(j=1;j<=i;j++)
f[dowh][j][1]=f[dowh^1][j-1][0];

if(i!=n)
{
for(j=i;j>=1;j--)
f[dowh][j][1]=(f[dowh][j][1]+f[dowh][j+1][1])%p;
for(j=1;j<=i;j++)
f[dowh][j][0]=(f[dowh][j][0]+f[dowh][j-1][0])%p;
}
}
dowh^=1;
for(i=1;i<=n;i++)
{
ans+=f[dowh][i][0];
ans%=p;
ans+=f[dowh][i][1];
ans%=p;
}
cout<<ans%p;
}


=================================2017.8.21=========================================

dp的时候我们主要的思路就是两条:1、存每一阶段的最优值,即可以给出每个k的答案

                                                                 2、把整体的信息写进dp,完成所有阶段才出一个k的解

  这个题就是第一种,考虑所有可能会对答案造成影响的信息,发现只有上一个数的大小会影响这个数数值的选择,于是就可以dp了

  (怎么感觉可以矩乘)

  真·插数dp




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