zoukankan      html  css  js  c++  java
  • 刷题总结——regular words(hdu1502 dp+高精度加法+压位)

    题目:

    Problem Description

    Consider words of length 3n over alphabet {A, B, C} . Denote the number of occurences of A in a word a as A(a) , analogously let the number of occurences of B be denoted as B(a), and the number of occurenced of C as C(a) . 

    Let us call the word w regular if the following conditions are satisfied: 

    A(w)=B(w)=C(w) ; 
    if c is a prefix of w , then A(c)>= B(c) >= C(c) . 
    For example, if n = 2 there are 5 regular words: AABBCC , AABCBC , ABABCC , ABACBC and ABCABC . 

    Regular words in some sense generalize regular brackets sequences (if we consider two-letter alphabet and put similar conditions on regular words, they represent regular brackets sequences). 

    Given n , find the number of regular words.

    Input

    There are mutiple cases in the input file. 

    Each case contains n (0 <= n <= 60 ). 

    There is an empty line after each case.

    Output

    Output the number of regular words of length 3n . 

    There should be am empty line after each case.

    Sample Input

    2 3

    Sample Output

    5 42

    Source


    Recommend

    xhd

    题解:

      dp方程很好想:用f[a][b][c]表示A有a个B有b个C有c个的单词的总数量,则f[a][0][0]=1,f[a][b][0]=f[a-1][b][0]+f[a][b-1][0],f[a][b][c]=f[a-1][b][c]+f[a][b-1][c]+f[a][b][c-1],只是要注意f可能过大··所以要用高精度顺便压下位····

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=61;
    const int Bit=10000;
    int f[N][N][N][30],n;
    inline void add(int f1[],int f2[])
    {
      int l1,l2;
      for(l1=29;!f1[l1];l1--);for(l2=29;!f2[l2];l2--);
      if(l1<l2)  l1=l2;
      for(int i=1;i<=l1;i++)  f1[i]+=f2[i];
      for(int i=1;i<=l1;i++)  f1[i+1]+=f1[i]/Bit,f1[i]%=Bit;
    }
    inline void W(int f1[])
    {
      int l1;
      for(l1=29;!f1[l1];l1--);
      cout<<f1[l1];
      for(int i=l1-1;i>=1;i--)
      {  
        if(f1[i]>=100&&f1[i]<1000)  putchar('0'); 
        else if(f1[i]>=10&&f1[i]<100)   putchar('0'),putchar('0');
        else if(f1[i]>=0&&f1[i]<10)  putchar('0'),putchar('0'),putchar('0');
        cout<<f1[i];  
      }
      cout<<endl;cout<<endl; 
    }
    inline void getans()
    {
      for(int i=1;i<=60;i++)
        for(int j=0;j<=i;j++)
          for(int k=0;k<=j;k++)
          {
            if(j==0)  f[i][j][k][1]=1;
            else if(k==0)
            {  
              add(f[i][j][0],f[i][j-1][0]);add(f[i][j][0],f[i-1][j][0]); 
            }
            else 
            {
              add(f[i][j][k],f[i-1][j][k]);add(f[i][j][k],f[i][j-1][k]);add(f[i][j][k],f[i][j][k-1]);
            }
          }
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      getans();
      while(~scanf("%d",&n))
        W(f[n][n][n]);
      return 0;
    }
  • 相关阅读:
    5555
    3333
    4444
    试验2
    Android之TextView灵活使用(转载)
    Android之使用Android-query框架进行开发(一)(转载)
    Android 之Html的解析(使用jsoup)
    Android之动画的学习(转载)
    Android之官方下拉刷新控件SwipeRefreshLayout
    Android之sqlite的使用 (转载)
  • 原文地址:https://www.cnblogs.com/AseanA/p/7652468.html
Copyright © 2011-2022 走看看