• 2016.7.15 NOIP2014模拟试题解题报告(又名:方克顺和他的正余弦朋友们(


        我发现自从我开始写博客以后OI成绩上升很明显啊orzzz,继续保持继续保持(然而昨晚上开夜车到十二点,感觉这次没发挥好)(下次没考好就尴尬了)(所以一定要考好!),嗯这次考得还是很不错的,也深入思考了一道题(感觉像重生一样),这套模拟题同样不火所以......百度云见orz http://pan.baidu.com/s/1jHFxJHc

    参考资料;

        1.同样不知哪来的解题报告:

        2.我机智的大脑;

        3.敬业的教练一枚;

    查漏补缺:

        1.盲打水平有待提高;

        2.递推是死穴;

        3.写搜索的速度要提高;

    考试分析:

        1.我才不会告诉你我这段时间的博客都是盲打的呢(这和考试有什么关系orz)

        2.这次做得很不错的一点是,基本没有浪费时间都在进行深入的思考,这也是这次能考好的一个原因,考试是需要估计和策略的,要合理分配时间把得分最大化,比如我今天就果断把时间都放在了第二题上,第三题没有分配时间,然后因为这套题比较难而我拿稳了第二题的100分所以考得非常不错,并且通过独立做出第二题这种我不擅长的递推,我感觉自己的水平也有了很大的进步;

        3.少开车,规范作息orz;

    一.合理种植

    题意:模拟找共线;n≤1,000,0≤x,y≤10,000。

    题目分析:抱着第一题肯定是送分的的思想,我在第一题面前懵比了近半个小时,最后忍痛写了50%,继续我”第一题永远不会全过“的诅咒;所以大家不要被以往的经验蒙蔽而打乱自己的节奏,这道题如果多花一点时间相信还是做得出来的,关键是观察力不够,找不到数据的特点,这一点还要提高,所以不要鄙视模拟题,人家要难还是会难起来的;这道题我的50%是三重循环,后面超时,这里还有一个需要注意的地方,就是按我的方法来判重的话,每两点都要记,不能漏;

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<set>
    using namespace std;
    const int MAXN=1005;
    long long ans;
    int x[MAXN],y[MAXN],jl[MAXN][MAXN],n,w,roa[MAXN];
    int main()
    {
        freopen("plant.in","r",stdin);
        freopen("plant.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d %d",&x[i],&y[i]);
        for(int i=1;i<=n-2;i++)    
        {memset(roa,0,sizeof(roa));w=0;
        for(int j=i+1;j<=n-1;j++)
        if(!jl[i][j])
        {int cs1=y[j]-y[i],cs2=x[j]-x[i],flg=0;    
        for(int k=j+1;k<=n;k++)
        if(cs1*(x[k]-x[j])==cs2*(y[k]-y[j]))
        {if(!flg){
        ans++;
        flg=1;}
        w++;
        for(int z=1;z<=w-1;z++)jl[roa[z]][k]=1;
        jl[i][k]=1;jl[j][k]=1;roa[w]=k;}}//后面的相互之间也要记,逻辑性 
                                           }
        printf("%I64d",ans);
        return 0;
    }

        然后正解应该是每个点罗列出来,算相应排序(用double记录),然后相同的就在一起了,时间复杂度为n方logn,老师让先不写,所以先留在这里;

    (这里的memset其实抱着能过几组过几组的尽量简化的思想的话是可以不写的,因为后面会覆盖,w置为0就可以了;(然后我改这部分改了好多次,之前为了少memset定成二维,结果w忘了在j处置0,不过调出来了,证明了我的猜想是正确的(也可能是数据比较水或者剪枝剪了很多)

       (所以不要脑抽,要全面思考,当然这不是说说就可以的,要通过多练题来达到)和我的两百分擦肩而过,但反正这不是终点,我一定会在最终属于我的战场上取得我满意的成绩的!

        还有,括号要打清楚,养成良好的编程习惯)

    二.排队:

    题意:1-n逆序对为k个的排列数;

    题目分析:这道题刚拿到的时候我没有把数据分析出来,后来有同学在抱怨手算了很久都没有找到规律,不过我觉得吧,规律都是建立在逻辑性上的,你不能找出一定的必然性,甚至通过推理得到规律的话,仅仅是找规律效率必然不高;在写了排列组合以后我突然发现了规律,原来每一位上能保证逆序对的数字是一定的且不受前后影响的(准确地说,是最后的结果不受影响),然后我就想起了很经典的递归+深搜模型,并且安慰自己这个大概还是蛮快的吧并且开始第三题,后来突然发现这道题可以用递推!然后就结了很久之后决定先写第三题然后再回来做第二题,从此再也没有时间看第二题orz,不过我还是很感激自己的决定,不然我应该没有这么高的分。(那个后来被其他同学证实只能过一组的程序被我用来对拍了,不过试大数据的时候十分钟都出不来(手动再见)(做找规律的题如果对自己的做法有点担心,或者是像我一样经常会写出打很多补丁支离破碎自己都担心的程序(当然,这种情况要改,要在写之前做好准备)或者是不知道错哪了需要数据调试都很需要对拍!所以一定要熟练运用不要一弄就是半个小时)

        我废话太多了......就当是练打字了,这道题的正解就是递推,由一种情况加起来,就是边界判断有点麻烦,以及初值也很麻烦,我是打了超多补丁的如果有其他的程序参考就不要看我混乱的程序了orz,(对了在写程序晕了的时候自己在旁边或者草稿纸上注释并且把它记在脑里检查对调试找错非常有用!)

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<set>
    using namespace std;
    int n,k,F[105],ff[105]; 
    long long ans,f[105][5005];
    const int M=1799999;
    int main()
    {
        freopen("lineup.in","r",stdin);
        freopen("lineup.out","w",stdout);
        scanf("%d %d",&n,&k);
        for(int i=2;i<=n;i++)
        {
        int cs=n-i;
        F[i]=cs*(cs+1)/2;
        ff[i-1]=(cs+n)*(i-1)/2;
        }
        f[n][0]=1;f[n-1][1]=1;f[n-1][0]=1;
        for(int i=1;i<=n;i++)
        {
        f[i][F[i]]=1; 
        }
        F[1]=k+1;
        for(int i=n-2;i>=1;i--)//在第i层如果已完成j个,后面一共的可能性有多少 
        for(int j=max(0,k-ff[i-1]);j<=min(k,F[i]-1);j++)
          //自下而上 
        {
            int zxz=max(0,j-n+i);zxz=max(zxz,j-F[i+2]-n+i);//正选的这
            //一层可能还有!站在逻辑的高度去思考问题! 
            int yxz=min(j,F[i+1]);
            for(int z=zxz;z<=yxz;z++)//在第i+1层已完成多少个 
            {
            f[i][j]+=f[i+1][z];
            f[i][j]%=M;
            }
        }
        ans%=M;
        printf("%I64d",f[1][k]);
        return 0;
    }

        注释的那个错就是折磨了我近一个小时让我时刻面对着只有50分的绝望的程序......因为在最后一个小时选择了调程序放弃最后一题的我真的是孤注一掷,所以啊......不要放弃.,.....

        注:可用前缀和简化,通过F[I][J],F[I][J-1]的递推式得——F[I][J]=F[I-1][J]+F[I][J-1]-F[I-1][J-1](观察数据关系

    三.科技节

    题意:每个m列有且只有一个1;

    题目分析:我一定要把我的程序发上来

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<set>
    using namespace std;
    int m,n,ovo[20][305];
    int main()
    {
        freopen("scifest.in","r",stdin);
        freopen("scifest.out","w",stdout);
        while(scanf("%d %d",&n,&m)==2)//虽然是骗分,也不要骗得栈溢出了啊orz 
        {
            for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            scanf("%d",&ovo[i][j]);
            printf("Yes
    ");
        }
        return 0;
    }

        嗯我之前骗分的时候把n和m写反了......所以同学们啊,骗分也要有专业精神......

        这道题的正解是搜索,一般只能过60%,然而......同学们啊你们还记得大明湖畔的位运算版N皇后问题吗......对的就是这样,位运算,一个神奇的东西(很难想到

        (还可以用A*先搜人多的点,加减枝可以过60%)

        

  • 相关阅读:
    软件下载
    01_动态规划之01背包问题
    25_使用切片建立一个动态的二位数组.go
    为什么突然想起来写博客
    24_切片的使用
    23_随机数的生成和冒泡排序
    22_数组做函数参数
    21_一维数组和二位数组的使用
    20_指针类型的使用
    19_获取命令参数
  • 原文地址:https://www.cnblogs.com/SindarDawn/p/5674394.html
Copyright © 2020-2023  润新知