zoukankan      html  css  js  c++  java
  • 2016.8.29 LGTB解题报告

    考试总结:

    1.这道题还是花了不少的时间的,特别是对拍啊之类的,总是放不下,然后有一些实现的问题导致改错也改了很久;

        解决方案:下一次在决定写程序的时候,一定要先在草稿纸上把实现算法的流程基本上写一次,精确到循环语句,判断语句的框架,把所有的情况都完整地考虑一次,确定没有问题了再写;

        这道题犯了和上一套第二题同样的问题:证明的时间过长;

    解决方案:在解题时把流程规范化,在证明了算法正确性以后就放下了,不要总是把它提出来!

    2.这道题的数据范围特别小,所以可以很容易地想到状压DP,然后考虑到互质的概念,就基本可以确定用位运算来表示质因数了,但是如果100个数考虑到极值100个数都变成质数的话,状压肯定是longlong存不下的,而NOIP难度很少考到比longlong范围大的状压,所以我最后只写了40分的程序,并且由于是第一次写状压,所以很荣幸地没调试出来,所以新学的知识点还是要做那么一两道题的,一是为了熟悉知识点与算法本质,二也是为了在考场上不至于那么害怕;然后正解分析了a<=30这个特性之后得出最多取到58,所以这说明,选定了一个算法之后就要去规范化地解决问题,比如边界比如初始化,而不是还盯着那个算法不知道干什么,专注于一个方面才能把这个方面做好

    3.看题;

    4.总结得出,我是那种只要文件和输入输出名没问题,没注销,仔细读了题就稳前3的人,当然,我这些方面经常出问题,所以一定要改;

    解题报告:

    一.LGTB与偶数:

    题意:相邻的数同为奇数可以删,同为偶数可以删;

    分析:如果遇到可以消的,那么消了以后也不会有坏的影响,因为如果本来被消的两个数也可以和另一边的消除,那么这两个数被删掉后旁边的数凑在一起也可以被消,反之,则本来也不能被消,所以遇到可以消除的就消除,那么一个偶数被消除后留下的肯定是一个奇数,所以就是线性的算法了;

    注意:在消的过程中可能出现消完的情况,这时之前的奇偶性已经没有用了,要特殊情况考虑;

    代码:

    #include<iostream>

    #include<cstdio>

    #include<cstring>

    using namespace std;

    const int maxn=2e9;

    int tmp,n,f,flg;

    int main()

    {

             freopen("even.in","r",stdin);

             freopen("even.out","w",stdout);

             scanf("%d",&n);f=1;

             scanf("%d",&tmp);if(tmp%2)flg=1;

             for(int i=2;i<=n;i++){

                       scanf("%d",&tmp);

                       if(!f){

                       if(tmp%2)flg=1;else flg=0;

                       f=1;

                 }

                       else if(tmp%2){

                         if(flg){f--;flg=0;}

                         else {f++;flg=1;}

                          }

                      else{

              if(flg){f++;flg=0;}

                         else {f--;flg=1;}

                       }

        }

        printf("%d",f);

             return 0;

    }

    二.LGTB与序列:

           题意:求由给定序列变成互质序列的最小增减数;

           分析:a<=30的特性可以分析得出a最多取到58,58以内素数很少所以可以直接状压质因子,提取出影响因素;对于选择很多的情况,直接枚举每个情况要比搜索还要节约时间(得多),然后会发现还是会超时,这时候,我们的神器——打表就出现啦!对于一个固定不变的东西,打表是很好的选择,对于a>b,变成数时肯定a变的数大一点比较优,所以快排;;

    程序:

    #include<iostream>

    #include<cstdio>

    #include<cmath>

    #include<cstring>

    #include<algorithm>

    using namespace std;

    int f[80005][105],map[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};

    int a[105];

    int bit[59]={0,0,1,2,1,4,3,8,1,2,5,16,3,32,9,6,1,64,3,128,5,10,17,256,3,4,33,2,9,512,7,1024,1,18,65,12,3,2048,129,34,5,4096,11,8192,17,6,257,16384,3,8,5,66,33,32768,3,20,9,130,513};

    int n;

    const int maxn=1<<16;

    bool cmp(int x,int y)

    {

      if(x>y)return true;

      else return false;

    }

    int main()

    {

      freopen("seq.in","r",stdin);

      freopen("seq.out","w",stdout);

      scanf("%d",&n);

      for(int i=1;i<=n;i++)scanf("%d",&a[i]);sort(a+1,a+n+1,cmp);

      memset(f,127,sizeof(f));

      for(int i=0;i<maxn;i++)f[i][0]=0;

      int mini=min(16,n);

      for(int i=1;i<=mini;i++)

        for(int j=0;j<maxn;j++)if(f[j][i-1]<2e9)

        for(int k=1;k<=58;k++)

      {

      if(bit[k]&j)continue;

      if(abs(a[i]-k)+f[j][i-1]<f[bit[k]|j][i])f[bit[k]|j][i]=abs(a[i]-k)+f[j][i-1];

      }

        int mini2=mini;mini=2e9;

        for(int i=1;i<maxn;i++)mini=min(mini,f[i][mini2]);

      for(int i=17;i<=n;i++)mini+=abs(a[i]-1);

      printf("%d",mini);

      return 0;

    }

         

    三.LGTB与大数

    题意:对一个字符串经行处理,每次把一个数字替换为一个数字串,最火输出这个数字串对1e9+7取mod的结果;

    分析:链表实现过了40分,存不下;正解是从后向前推每个数字最后变成了哪个数,这样可以确定排除这个数代表的数又被改了的问题,是一种操作的逆向化,这道题也要小心纪录转换成的数字串的长度可能会超范围,而长度的唯一作用就是用来快速幂,所以可以直接mod(运用费马小定理,注意1e9+7是质数!这是一条很重要的性质!(虽然没有很强的指向性))

    程序:

    #include<iostream>

    #include<cstdio>

    #include<cstring>

    #include<string>

    using namespace std;

    long long ans,m[10][100005],ll[11];

    long long len[100010],n;

    string tov[100005],tmp;

    char fr[100010],a[100005];

    const int mod=1000000007;

    /*int qpow(int u)

    {

             u%=mod-1;int an=10;

             if(!u)return 1;u--;

             while(u){

                       if(u&1)an*=10;

                       if(u!=1)an*=an;

                       an%=mod;

                       u>>=1;

        }

        return an;

    }*/

    long long qpow(long long b)

    {

        b%=mod-1;long long an=10;

             long long ss=1;

        while(b)

        {

            if(b&1) ss=ss*an,ss%=mod;

            an*=an,an%=mod;

            b>>=1;

        }

        return ss;

    }

    int main()

    {

             freopen("number.in","r",stdin);

             freopen("number.out","w",stdout);

             scanf("%s",a);scanf("%I64d",&n);

             for(int i=1;i<=n;i++){

                       getchar();

                       cin>>tmp;//cout<<tmp;

                       fr[i]=tmp[0];

                       len[i]=tmp.size()-3;

                       tov[i]=tmp.substr(3,len[i]);

             }

             for(int i=0;i<=9;i++){

             m[i][n+1]=i;ll[i]=1;}

             for(int i=n;i>=1;i--)for(int k=0;k<=9;k++)if(k==fr[i]-'0'){             

             long long tot=0;

             for(int j=0;j<len[i];j++)if(ll[tov[i][j]-'0']){

                       int ns=tov[i][j]-'0';

             m[k][i]*=qpow(ll[tov[i][j]-'0']);m[k][i]%=mod;

             m[k][i]+=m[tov[i][j]-'0'][i+1];m[k][i]%=mod;

             tot+=ll[tov[i][j]-'0'];tot%=mod-1;

             }

             ll[k]=tot;if(!ll[k])ll[k]=mod-1;

        }

        else{

                 m[k][i]=m[k][i+1];

        }

             long long l=strlen(a);

             for(int i=0;i<l;i++){

        ans*=qpow(ll[a[i]-'0']);ans%=mod;

             ans+=m[a[i]-'0'][1]; ans%=mod;

             }

             printf("%I64d",ans%mod);

             return 0;

    }

  • 相关阅读:
    UVA 10935 约瑟夫环
    分拆素数和 埃氏筛法
    POJ 2349 Prim
    POJ 2031 prim
    POJ 1861 Kruskal
    POJ 2395 Prim
    POJ 1751 Prim
    POJ 2421 Prim
    vuejs开发环境搭建及热更新
    vuejs介绍
  • 原文地址:https://www.cnblogs.com/SindarDawn/p/5818649.html
Copyright © 2011-2022 走看看