5
27
2016
0

【新姿势】数位Dp学习

先发上来一些题目的std程序,开坑啦

bzoj1026 Windy数

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1026

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

int A[12];

int f[12][10];

//f[i][j]代表长度为i,最高位为j的windy数个数
void init()
{
   memset(f,0,sizeof(f));
   for(int i=0;i<10;i++) f[1][i] = 1;
   for(int i=2;i<=10;i++)
   {
      for(int j=0;j<10;j++)
      {
         for(int k=0;k<10;k++)
         {
            if(abs(j-k)>1) f[i][j] += f[i-1][k];
         }
      }
   }
}
//(0,a)范围内的windy数个数
int calc(int a)
{
   int m = 0;
   while(a)
   {
      A[m++] = a%10;
      a/=10;
   }
   int ans = 0;
   //先处理长度小于m的windy数的个数
   for(int i=1;i<m;i++)
   {
      //题目要求不含前导0
      for(int j=1;j<10;j++)
      {
         ans += f[i][j];
      }
   }
   //长度等于m且最高位和原数不同且小于原数的windy数
   for(int j=1;j<A[m-1];j++) ans += f[m][j];
   //依次循环将最高位 变为和原数相同
   for(int i=m-1;i>=1;i--)
   {
      for(int j=0;j<A[i-1];j++)
      {
         if(abs(j-A[i]) > 1) ans += f[i][j];
      }
      if(abs(A[i] - A[i-1])<=1) break;
   }
   return ans;
}


int main()
{
   #ifndef ONLINE_JUDGE
      freopen("in.txt","r",stdin);
   #endif
   int a,b;
   init();
   while(scanf(" %d %d",&a,&b)!=EOF)
   {
      int ans = calc(b+1) - calc(a);
      printf("%d\n",ans );
   }
   return 0;
}


09 刘聪论文  Amount of degrees

传送门:http://oj.bashu.com.cn/code/problempage.php?problem_id=3198

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

int f[35][35];
int d[35];
//高度为i(i>=0)时,含有j个1的个数
void init()
{
   memset(f,0,sizeof(f));
   f[0][0] = 1;
   for(int i=1;i<=31;i++)
   {
      f[i][0] = 1;
      for(int j=1;j<=i;j++)
      {
         f[i][j] = f[i-1][j-1] + f[i-1][j];
      }
   }
}
//[0,x]范围内二进制含有k个1的个数
int calc(int x,int k)
{
   //路径上含有的1的个数
   int tot = 0;
   int ans = 0;
   for(int i=31;i>0;i--)
   {
      if(x&(1<<i)) 
      {
         tot++;
         if(tot>k) break;
         x ^= (1<<i);
      }
      if((1<<(i-1))<=x) ans += f[i-1][k-tot];
   }
   if(tot + x == k) ans++;
   return ans;
}
//b进制转化为二进制
int transfer(int b,int x)
{
   int m = 0;
   int ans = 0;
   while(x)
   {
      d[m++] = x % b;
      x/=b;
   }
   for(int i=m-1;i>=0;i--)
   {
      if(d[i]>1) 
      {
         for(int j=i;j>=0;j--) ans |= (1<<j);
      }
      else ans |= d[i]<<i;
   }
   return ans;
}
int main()
{
   #ifndef ONLINE_JUDGE
      freopen("in.txt","r",stdin);
   #endif
   int x,y;
   int k,b;
   init();
   while(scanf(" %d %d",&x,&y)!=EOF)
   {
      scanf(" %d %d",&k,&b);
      x = transfer(b,x-1);
      y = transfer(b,y);
      printf("%d\n",calc(y,k) - calc(x,k));
   }
   return 0;
}



 

Category: 树套树 | Tags: | Read Count: 206

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com