预处理求出所有答案,再根据具体数字求解,模板性较强。
DP版要想方程,所以还是记忆化搜索版容易,就是枚举每一位。
看http://blog.csdn.net/synapse7/article/details/21006265?utm_source=tuicoo的注释大概能懂。
递归版利用了bit从1计数,而参数按0计数。如
23则bit[1]=3,bit[2]=2,传len=2进去,然后for遍历bit[2]顺便把len-1递归下去,然后len=1时遍历bit[1]=3,继续传0进去,然后返回
HDU 3555 BOMB 不含49
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin)
ll dp[25][3]; //dp[i][j]:i长度j情况
//dp[i][0] 长度为i且不含49
//dp[i][1] 长度为i不含49但以9开头
//dp[i][2] 长度为i含49
int bit[25];
void init()
{
CLR(dp,0);
dp[0][0] = 1;
for(int i=1;i<=20;i++) //2^63次方在20位以内
{
dp[i][0] = dp[i-1][0]*10-dp[i-1][1]; //不含49*10-补上4组成的49
dp[i][1] = dp[i-1][0]; //补上9
dp[i][2] = dp[i-1][2]*10+dp[i-1][1]; //已含49*10+补上4组成的49
}
}
int main()
{
//RE;
int t;
ll n;
init();
cin>>t;
while(t--)
{
cin>>n;
n++;
int len = 0;
ll ans = 0;
while(n)
{
bit[++len] = n % 10;
n /= 10;
}
bit[len+1] = 0;
bool flag = false;
for(int i=len;i>=0;i--)
{
ans += dp[i-1][2]*bit[i]; //低位含49的*该位数字
if(flag)
ans += dp[i-1][0]*bit[i]; //组成49后就+=低位*该位
if(!flag && bit[i]>4) //后一位是9,那么数字大于4的都包含49
ans += dp[i-1][1];
if(bit[i]==9 && bit[i+1]==4) //组成49
flag = true;
}
cout<<ans<<endl;
}
}
递归版
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=25;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;
int bit[maxn];
ll dp[maxn][2][2];
ll dfs(int len,bool is4,bool ok49,bool ismax){
if(len<=0) return ok49?1:0;
if(!ismax && dp[len][is4][ok49] != -1) return dp[len][is4][ok49];
int pmax = ismax ? bit[len] : 9;
ll cnt = 0;
for (int i = 0; i <= pmax; ++i){
cnt += dfs(len - 1,i == 4,ok49 || (is4 && i == 9),ismax && i == pmax);
}
return ismax ? cnt : dp[len][is4][ok49] = cnt;
}
ll solve(ll n){
int cnt=0;
while(n){
bit[++cnt]=n%10;
n/=10;
}
return dfs(cnt,false,false,true);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
ll a,t;
memset(dp,-1,sizeof(dp));
cin>>t;
while(t--){
cin>>a;
cout<<solve(a)<<endl;
}
return 0;
}
HDU 2089 不要62 不含4和相邻62的数
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define Q_CIN ios::sync_with_stdio(false)
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin)
int dp[10][3];
//dp[i][0] 长度为i,无不吉利且不以2开头
//dp[i][1] 长度为i,无但以2开头
//dp[i][2] 长度为i,有
int bit[10];
void init()
{
CLR(dp,0);
dp[0][0] = 1;
for(int i=1;i<=10;i++)
{
dp[i][0] = dp[i-1][0]*9-dp[i-1][1]; //除4外的9个-后一位是2的情况
dp[i][1] = dp[i-1][0]; //直接加2
dp[i][2] = dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0]; //原有的+加6的+加4的
}
}
int solve(int n)
{
int len = 0;
int ans = 0;
int tmp = n;
while(n)
{
bit[++len] = n % 10;
n /= 10;
}
bit[len+1] = 0;
bool flag = false;
for(int i=len;i>=0;i--)
{
ans += dp[i-1][2]*bit[i];
if(flag)
ans += dp[i-1][0]*bit[i];
if(!flag && bit[i]>6)
ans += dp[i-1][1];
if(!flag && bit[i]>2&&bit[i+1]==6)//62x
ans += dp[i][1]; //dp[i][1]
if(!flag && bit[i]>4)
ans += dp[i-1][0];
if((bit[i]==2 && bit[i+1]==6)||bit[i]==4)
flag = true;
}
return tmp-ans; //求没有不吉利的
}
int main()
{
// RE;
int n,m;
init();
while(cin>>n>>m,m||n)
{
CLR(bit,0);
cout<<solve(m+1)-solve(n)<<endl; //[n,m]=[1,m]-[1,n)
}
return 0;
}
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=10;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;
int bit[maxn];
int dp[maxn][2];
int dfs(int len,bool is6,bool ismax){
if(len==0) return 1;
if(!ismax&&dp[len][is6]>=0) return dp[len][is6];
int cnt=0,pmax=(ismax?bit[len]:9);
for (int i = 0; i <= pmax; ++i){
if(i==4||(is6&&i==2)) continue;
cnt+=dfs(len-1,i==6,ismax&&i==pmax);
}
return ismax?cnt:dp[len][is6]=cnt;
}
int solve(int n){
int cnt=0;
while(n){
bit[++cnt]=n%10;
n/=10;
}
return dfs(cnt,false,true);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
int a,b;
memset(dp,-1,sizeof(dp));
while(cin>>a>>b,a||b){
cout<<solve(b)-solve(a-1)<<endl;
}
return 0;
}
POJ 3252 Round Numbers
求[x,y]区间内“二进制表示0比1多的数”的个数。处理前导0,前导0不算0。
dp[len][num0][num1]:长度为len,0的数量为num0,1数量为num1的个数
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=50;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;
int bit[maxn];
int dp[maxn][maxn][maxn];
int dfs(int len,int num0,int num1,bool first,bool ismax){
if(len==0) return num0>=num1?1:0;
if(!ismax && dp[len][num0][num1] != -1) return dp[len][num0][num1];
int pmax = ismax ? bit[len] : 1;
int cnt = 0;
for (int i = 0; i <= pmax; ++i){
if(first){
if(i==0)
cnt += dfs(len-1,0,0,true,ismax&&i==pmax);
else
cnt += dfs(len-1,0,1,false,ismax&&i==pmax);
}else{
if(i==0)
cnt += dfs(len-1,num0+1,num1,false,ismax&&i==pmax);
else
cnt += dfs(len-1,num0,num1+1,false,ismax&&i==pmax);
}
}
return ismax ? cnt : dp[len][num0][num1] = cnt;
}
int solve(int n){
int cnt=0;
while(n){
bit[++cnt]=n%2;
n/=2;
}
return dfs(cnt,0,0,true,true);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
int a,t,b;
memset(dp,-1,sizeof(dp));
while(cin>>a>>b)
cout<<solve(b)-solve(a-1)<<endl;
return 0;
}
弱校OJ 233数
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=50;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;
int bit[maxn];
ll dp[maxn][2][2][2]; //长度,是不是1,是不是23,是不是233
ll dfs(int len,bool is2,bool is23,bool ok,bool ismax){
if(len<=0) return ok?1:0;
if(!ismax && (dp[len][is2][is23][ok] != -1)) return dp[len][is2][is23][ok];
int pmax = ismax ? bit[len] : 9;
ll cnt = 0;
for (int i = 0; i <= pmax; ++i){
cnt += dfs(len - 1,i==2,is2&&i == 3,ok||(is23&&i==3),ismax && i == pmax);
}
return ismax ? cnt : dp[len][is2][is23][ok] = cnt;
}
ll solve(ll n){
int cnt=0;
while(n>0){
bit[++cnt]=n%10;
n/=10;
}
return dfs(cnt,false,false,false,true);
}
int main()
{
// #ifndef ONLINE_JUDGE
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
// #endif
ll a,t;
memset(dp,-1,sizeof(dp));
cin>>t;
while(t--){
cin>>a;
cout<<solve(a)<<endl;
}
return 0;
}
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false);
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define bug(x) cout<<#x<<":"<<(x)<<endl;
#define sf(a) scanf("%d",&a)
#define sff(a,b) scanf("%d%d",&a,&b)
#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=20;
const int maxm=1e6+5;
const int inf = 0x3f3f3f3f;
int bit[maxn];
ll dp[maxn][2][2][13]; //dp[i][j][k][k]:长度为i,是否以1结尾,有无13,模13的结果
ll dfs(int len,bool end1,bool have13,int mod,bool ismax){
if(len==0) return (!mod && have13);
if(!ismax && (dp[len][end1][have13][mod] != -1)) return dp[len][end1][have13][mod];
int pmax = ismax ? bit[len] : 9;
ll cnt = 0;
for (int i = 0; i <= pmax; ++i){
int tmod = (mod*10+i) % 13;
cnt += dfs(len-1,i==1,have13||(end1&&i==3),tmod,ismax && i == pmax);
}
return ismax ? cnt : dp[len][end1][have13][mod] = cnt;
}
ll solve(ll n){
int cnt=0;
while(n>0){
bit[++cnt]=n%10;
n/=10;
}
return dfs(cnt,false,false,0,true);
}
int main()
{
ll a,t;
memset(dp,-1,sizeof(dp));
while(cin>>a){
cout<<solve(a)<<endl;
}
return 0;
}