Codeforces eduR42 C(枚举)

既然蓝桥杯过了,从今日起恢复每日打卡。

传送门:点击打开链接

每日打卡(1/1)

题目大意:

    给你一个正整数(1-2e9),要求出至少删去其中几个数字,才能让它变成一个完全平方数。

思路一

    也是我想的思路,对于数n的每一位,我们都有删或者不删两种操作,也就是说,至多求2^9次后,我们就能得到结果。

而如何枚举成了我的另一个问题,之前写的dfs一直出错。

    所以,还是参考了以前写的一篇文章的枚举法。

    

for(int i=0;i<(1<<len);i++)
 dfs(i,s);
for(int j=0;j<len;j++)
{
	if((k>>j)&1)
	{
		 del(j);
	}
}

这样一来,就枚举完成了所有的情况。

    这时候我们可以依次选择删或者不删,删完后再判断是否是平方数。

    在第一次的写法中,我将字符串s中删去的值记为0,,结果WA了。这显然是不可取的,举个栗子,输入n=101,正确结果为2,可是输出的全是1,原因就是将删去的末位1记为了0,导致错误。。

    而将这个bug修复后,又出现了新的错误,在上述例子中,输出的依然是1。仔细思考后发现,如果删去百位上的1,那么原数就记为了 01 ,依然属于合法的。

    因此,做了第二个改进,将数字首位的0全部去掉。。

    

while(1)
{
	if(q.front()==0)
	 q.pop();
	else 
	 break;
}

   

    然后又RE了,原来是如果输入0(还有其他例子),它就会死循环。。。

    因此,再循环条件中加上 !q.empty()。

最后,我们得到了AC解法

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
const int inf = 0x3f3f3f3f;

string s;
int len,ans,tot,a[maxn];

bool check(string s)
{
	queue<int> q;
	int n = s.length();
	for(int i=0;i<n;i++)
	{
		if(s[i]!='*')
			q.push(s[i]-'0');
	}
	while(1&&!q.empty())
	{
		if(q.front()==0)
		 q.pop();
		else 
		 break;
	}
	tot = len-q.size();
	if(!q.empty()) {
		int x = q.front();
		q.pop();
		while(!q.empty())
		{
			x = x*10+q.front();
			q.pop();
		}
	  	int temp = sqrt(x);
	  	if(temp*temp==x)
  		{
  //			cout<<x<<endl;
  				return true;
  		}
	}
  	return false;
}

void del(int x)
{
	a[x] = !a[x];
}

void dfs(int k,string s)
{
//	cout<<k<<endl;
	memset(a,0,sizeof(a));
	tot = 0;
	for(int j=0;j<len;j++)
	{
		if((k>>j)&1)
		{
			 del(j);
		}
	}
	
	for(int i=0;i<len; i++)
	{
		if(a[i])
		{
			s[i] = '*';
		} 
	}
//	cout<<s<<endl;
	if(check(s)) {
		ans = min(ans,tot);
	}
}

int main()
{
	cin>>s;
	len = s.length();
//	cout<<len<<endl;
	ans = inf;
	for(int i=0;i<(1<<len);i++)
	 dfs(i,s);
	if(ans==inf) {
		cout<<-1<<endl;
		return 0;
	}
	cout<<ans<<endl;
	return 0;
} 


思路二

    在CSDN上看到有一位仁兄提供了一个思路。

    就是枚举1-n范围内的所有完全平方数,然后将每一个数于n相比,比较它们相同的位数,尽量取大的。

很显然,最终结果就是 n的长度-相同位数长度最大值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

总想玩世不恭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值