HDU-1111解题报告

一个蒟蒻的吐槽:

我英语不是很好,经常遭到读题杀,但这种一路看下去几乎每个单词都懂却仍一脸懵逼的题目还是比较少见,虽然我英语烂,但它的写法也要背锅!!!(B^n直接写成Bn真的好码?)


题目大意:

给定一个复数X的实部xr和虚部xi,求将其转为B进制后上的每一位数。B为一个复数,X和B的实部和虚部都为整数。要求转为B进制后每一位数都是整数。最后结果至多100位,超过一百位可视为无解。


思路:

假如X能被分解,那么肯定是分解为以下形式

X = a0 + a1*B^1 +a2*B^2 +…+an*B^n = a0 + B( a1 + B(a2 + B(… B*an )));

那么我们只需要从a0开始DFS,若X-a0 后得到的复数可被B整除则说明a0可能为解的一元。因为易知“+”之后的部分实部和虚部都是整数,不可能使除以B后得到的复数的实部或虚部出现小数。除了这个剪枝还要注意a的取值范围是一定要求小于|B|的,然后用这两个剪枝,就可以较轻松的搜索下去了。

关于复数相除后实部、虚部是否为整数的判断:详细的我也不说了,这个百度、谷歌到处都是,学过的也能很快明白,我就直接列出式子满足不想细学又要做这道题的人。

若复数A = a + b * i; B = c + d * i; (i为虚数单位) 

A可被B整除等价于 (a*c+b*d)%(c*c+d*d)==0 && (b*c-a*d)%(c*c+d*d)==0

#include 
#include 
#include 
#include 

const int MAXN = 128;

long long a,b,c,d,mod,t,flag,num,i;
long long ans[MAXN];

void Dfs(long long a, long long b, long long step)
{
	if (step > 100)	return;
	if (a==0 && b==0)
	{
		flag = 1;
		num = step;
		return;
	}

	long long x,y,i;

	for (i=(int)sqrt(mod-1); i>=0; --i)
	{
		x = (a-i)*c+b*d;
		y = b*c-(a-i)*d;
		ans[step] = i;
		if ( x%mod==0 && y%mod==0 )
			Dfs(x/mod,y/mod,step+1);
		if (flag)	return;
	}
}

int main()
{
	for (scanf("%I64d",&t); t>0; --t)
	{
		scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d);
		flag = 0;
		mod = c*c +d*d;
		Dfs(a,b,0);
		if (flag==0)	printf("The code cannot be decrypted.\n");
		else
		{
			if (num == 0)	printf("0\n");
			for (i=num-1; i>=0; --i)
				if (i!=0)	printf("%I64d,",ans[i]);
				else	printf("%I64d\n",ans[i]);
		}
	}
	return 0;
}

几个坑。。。。

  1. 这里要用__int64或long long,int不够大。
  2. 若输入数据的xr和xi都为0,不注意很可能会导致没有输出。
  3. 这题似乎根本没有spj,搜索时要将a从小到大枚举。
  4. 是的,对于下面这组数据答案为无解(不要问我为什么。。。。。)
1

0 1 0 1

HDU-1111 原题请戳这里

你可能感兴趣的:(解题报告)