windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
标签:
为了搞SCOI的几道题先做水数位。
之前听过课,半懂不懂吧,现在清楚了些。
这类题一般满足区间减法,即只需要我们求出(1,n)即可,然后打表也是为了sovle(DataType)服务。
先想好怎么计算,再去想怎么打表。
计算是一般存在这样的问题,就是比如n=abcdef,当a=6时,6开头的不能全算,那就只能先算1~5,然后理解为把6摆好,算下一位,这样我们发现,这个函数是没有包含n这个数的,所以调用是要调用sovle(n+1)
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 using namespace std; 7 8 int dp[10][3];//dp[i]表示第i位,dp[i][0]吉利的,dp[i][1]第一位为2的吉利的,dp[i][2]为不吉利的 9 void table_maker() { 10 dp[0][0]=1; 11 for(int i=1;i<=6;i++){ 12 dp[i][0]=dp[i-1][0]*9-dp[i-1][1]; 13 dp[i][1]=dp[i-1][0]; 14 dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0]; 15 } 16 } 17 int calc(int n) { 18 int a[10]={0},ans=0,flag=0,tmp=n*10,len=0; 19 for(;tmp/=10;)a[++len]=tmp%10; 20 for(int i=len;i>=1;i--){ 21 ans+=a[i]*dp[i-1][2]; 22 if(flag)ans+=a[i]*dp[i-1][0]; 23 else{ 24 if(a[i]>4)ans+=dp[i-1][0]; 25 if(a[i]>6)ans+=dp[i-1][1]; 26 if(a[i+1]==6&&a[i]>2)ans+=dp[i][1]; 27 if(a[i]==4||(a[i+1]==6&&a[i]==2))flag=1; 28 } 29 } 30 return n-ans; 31 } 32 33 int main() { 34 freopen("in.txt","r",stdin); 35 // freopen("out.txt","w",stdout); 36 37 table_maker(); 38 for(int l,r;~scanf("%d%d",&l,&r)&&(l||r);)printf("%d\n",calc(r+1)-calc(l)); 39 return 0; 40 }
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<stdio.h> 6 using namespace std; 7 #ifndef UNIX 8 #define LL "%I64d" 9 #else 10 #define LL "%lld" 11 #endif 12 const int N=20; 13 typedef long long ll; 14 ll dp[N][3],x;// dp[][0]不含49 dp[][1]不含49首位为9,dp[][2]含49 15 void mk_tb() { 16 dp[0][0]=1; 17 for(int i=1; i<N; i++) { 18 dp[i][0]=dp[i-1][0]*10-dp[i-1][1]; 19 dp[i][1]=dp[i-1][0]; 20 dp[i][2]=dp[i-1][2]*10+dp[i-1][1]; 21 } 22 } 23 ll f(ll n) { 24 ll tmp=n,ans=0; 25 int a[N]={0},flag=0; 26 for(*a=0; tmp; tmp/=10)a[++*a]=tmp%10; 27 for(int i=*a; i; i--) { 28 ans+=a[i]*dp[i-1][2]; 29 if(flag)ans+=a[i]*dp[i-1][0]; 30 else { 31 if(a[i]>4)ans+=dp[i-1][1]; 32 if(a[i+1]==4 && a[i]==9)flag=1; 33 } 34 } 35 return ans; 36 } 37 int main() { 38 freopen("in.txt","r",stdin); 39 freopen("","w",stdout); 40 mk_tb();int n; 41 for(scanf("%d",&n);n--;){ 42 scanf(LL,&x); 43 printf(LL"\n",f(x+1)); 44 } 45 46 return 0; 47 }
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
包含两个整数,A B。
一个整数。
【数据规模和约定】
100%的数据,满足 1 <= A <= B <= 2000000000 。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstdio> 6 #include<numeric> 7 using namespace std; 8 typedef int ll; 9 const int N=10; 10 ll dp[N+1][10];//dp[i][j]表示第i位为j的windy数的个数 11 void mk_tb(){ 12 for(int i=0;i<=9;i++)dp[1][i]=1; 13 for(int i=2;i<=N;i++){ 14 for(int j=0;j<=9;j++){ 15 for(int k=0;k<=9;k++){ 16 if(abs(j-k)>=2){ 17 dp[i][j]+=dp[i-1][k]; 18 } 19 } 20 } 21 } 22 } 23 ll f(ll n){ 24 int ans=0,a[N+1]={0},len=0; 25 for(int tmp=n;tmp;tmp/=10)a[++len]=tmp%10; 26 for(int i=1;i<len;i++)ans+=accumulate(dp[i]+1,dp[i]+N,0); 27 for(int i=1;i<a[len];i++)ans+=dp[len][i]; 28 for(int i=len;--i;){ 29 for(int j=0;j<a[i];j++)if(abs(j-a[i+1])>=2)ans+=dp[i][j]; 30 if(abs(a[i]-a[i+1])<2)break; 31 } 32 return ans; 33 } 34 int main() { 35 freopen("in.txt","r",stdin); 36 freopen("","w",stdout); 37 38 mk_tb(); 39 int a,b; 40 scanf("%d%d",&a,&b); 41 printf("%d\n",f(b+1)-f(a)); 42 43 return 0; 44 }
数位DP初步 bzoj1026 hdu2089 hdu3555
标签:
原文地址:http://www.cnblogs.com/showson/p/4297141.html