ACdream 1064 完美数

http://acdream.info/problem?pid=1064



求L到r之间含有3不含有8 或者 含有8不含有3的数的数量。
大思路就是用1-r符合条件的数减去1-(L-1)符合条件的数。
至于求有多少个,就是数位dp的知识了,从高位开始向后去数。
可以先将前10,100,1000,10000,100000等中包含一个数不包含另一个数的情况打表算出来。
算的时候要注意算到后面的位数的时候要标记前面高位有无出现3或者8.




#include<bits/stdc++.h>
using namespace std;
long long int ans1[22]={0,1,17,217,2465,26281,269297,2685817,26269505,253202761};
long long int ans2[22]={0,9,81,81*9,81*81,81*81*9,81*81*81,81*81*81*9,81*81*81*81,81*81*81*81*9};
long long int find(char a[])
{
	int l=strlen(a);
	long long int ans=0;		bool f1=0,f2=0;
	int i;
	for(i=0;i<=l-2;i++)
	{
        if(f1==0&&f2==0)
        {
        	if(a[i]<='3')
        	{
        		ans+=ans1[l-i-1]*2*(a[i]-'0');
			}
			else if(a[i]>'3'&&a[i]<='8')
			{
				ans+=ans1[l-i-1]*(2*(a[i]-'0'-1))+ans2[l-i-1];
			}
			else ans+=ans1[l-i-1]*(2*(a[i]-'0'-2))+ans2[l-i-1]*2;
		}
		if(f1==1&&f2==0)
		{
		 if(a[i]<='8')
			{
				ans+=ans2[l-i-1]*(a[i]-'0');
			}
			else ans+=ans2[l-i-1]*((a[i]-'0')-1);
		}
		if(f1==0&&f2==1)
		{
			if(a[i]<='3')
			{
				ans+=ans2[l-i-1]*(a[i]-'0');
			}
			else ans+=ans2[l-i-1]*((a[i]-'0')-1);
		}
		if(a[i]=='3')f1=1;
		if(a[i]=='8')f2=1;
	}
	if(f1==0&&f2==0)
	{
		if(a[l-1]<'3');
		else if(a[l-1]>='8')ans+=2;
		else ans+=1;
	}
	if(f1==1&&f2==0)
	{
		if(a[l-1]>='8')
		ans+=a[l-1]-'0';
		else ans+=a[l-1]-'0'+1;
	}
	if(f1==0&&f2==1)
	{
		if(a[l-1]>='3')
		ans+=a[l-1]-'0';
		else ans+=a[l-1]-'0'+1;
	}
	return ans;
}
int main(){
    char a[111],b[111];
    int n;
    cin>>n;
    while(n--)
    {
    	cin>>a>>b;
    	long long int ans=find(a);
    	long long int ans12=find(b);
    	bool f1=0,f2=0;
    	for(int i=0;i<strlen(a);i++)
    	{
    		if(a[i]=='3')f1=1;
    		if(a[i]=='8')f2=1;
		}
		if(f1!=f2)
		ans--;
		//cout<<ans<<" "<<ans12<<endl;
		cout<<ans12-ans<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值