SPOJ 370 - Ones and zeros (ONEZERO)
SPOJ 370 - Ones and zeros (ONEZERO)
我正在尝试解决SPOJ问题" 1和0 ":
某些正整数的十进制表示只有1和0,并且至少有一个数字1,例如101。如果一个正整数不具有这样的性质,我们可以试着用它乘以某个正整数,看看乘积是否具有这样的性质。
我解决这个问题的方法就是简单地做BFS。取只包含'1'
的字符串,然后对其进行BFS,每一步添加'1'
和'0'
。一直跟踪字符串形式的数字和余数直到现在。当余数为零时,表示找到该数字。
我的问题是:我的代码花了太长时间测试用例,例如9999或99999。如何改进算法的运行时间?
// Shashank Jain
/*
BFS
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <climits>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#define LL long long int
using namespace std;
LL n;
string ans;
void bfs()
{
string str,first,second;
str+='1'; // number will start with '1' always
if(n==1)
{
ans=str;
return;
}
queue<pair<string,LL> >q; // pair of STRING(number) and long long int
// (to hold remainder till now)
pair<string,LL>p;
p=make_pair(str,1);
q.push(p);
LL rem,val,temp;
while(q.empty()==0)
{
p=q.front();
q.pop();
str=p.first;
val=p.second;
if(val==0) // remainder is zero means this is number
{
ans=str;
return ;
}
// adding 1 to present number
temp=val*10+1;
rem=(temp)%n;
firstone=str+'1';
p=make_pair(firstone,rem);
q.push(p);
// adding 0 to present number
temp=val*10+0;
rem=(temp)%n;
secondone=str+'0';
p=make_pair(secondone,rem);
q.push(p);
}
}
int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
bfs();
for(i=0;i<ans.size();i++)
{
printf("%c",ans[i]);
}
printf("n");
}
return 0;
}
我刚刚解决了这个问题。我不会发布我的代码片段,但我会给出为什么你的代码较慢的点
-
sukunrt说你需要访问数组的大小n,在那里你可以获得当前模数标记为参观,这样你就不会再次访问它,因为如果你在一个已经访问了模量不需要考虑到目前为止获得的字符串的一部分,因为它只会让更大的数量(我们需要最低),即你说这意味着一旦你参观一个模数
x
然后你发现至少出x
0和1组成的数量除以n的余数。 -
您总是将获得的字符串传递给子线程,这不仅增加了内存,还增加了时间。为了避免这种情况,只需再取两个大小为n的数组,例如
value[]
和parent[]
。parent[i]
存储了模数i
的父模数value[i]
存储的是模数i
(0 <= i <n)>最后,你可以只在模数=0的情况下回溯得到整数。
同样在进行更改后,您的代码将给出WA,因为您必须首先通过在末尾附加"0"获得子,然后通过在末尾附加"1"获得子。(你可以自己证明)
这里有一个提示。这样想:
假设你想要的数字是X。X mod N = 0.
所以你只需要存储N个状态,即0-n-1。从1开始。然后做闺蜜。你需要抛弃那些余数与之前相同的分支。我把证明留给你。