HDU 4282 A very hard mathematic problem [剪枝/二分]

这题暴力+剪枝就可以过,重点是一个强剪枝:当z=2时,用完全平方公式解,直接得出符合的解数。

或者二分y,因为当x、z确定时,f是y的增函数。

但是二分我不知道为什么用while(low<high)的时候,写不对。。[mark]


1、暴力+剪枝

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef __int64 int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

//	z = [2, 30].
//	把z=2的提出来单独用 完全平方公式 考虑,是强剪枝。

int64 ex(int x, int y)	//x^y	,返回int64,为判断爆int32留有余地
{
	int64 ret = 1, now = x;
	for( ; y; y>>=1, now*=now)
	{
		if(y&1)
			ret*=now;
	}
	return ret;
}

int main()
{
	int k;
	while(scanf("%d", &k)!=-1 && k)
	{
		int64 ans = 0;
		int qr = (int)sqrt(k*1.0);
		if(qr*qr == k)		// 最优化剪枝,当z=2时。
		{
			ans += (qr-1)>>1;
		}
		FOR(z, 3, 30)
		{
			for(int x = 1; ; x++)
			{
				int64 t1 = ex(x, z);
				if(t1 + ex(x+1, z) + x*(x+1)*z > k) break;	//可行性剪枝
				for(int y = x+1;  ; y++)
				{
					int64 f = t1 + ex(y, z) + x*y*z;
					if(f > k) break;	//可行性剪枝
					else if(f == k)
					{
						//bug(z);bug(x);bug(y)<<endl;
						ans++;
						break;	//x、z确定后,f是y的增函数,显然 y是唯一的。	//可行性剪枝
					}
				}
			}
		}
		printf("%I64d\n", ans);
	}
}

2、二分

用while(low<=high)的写法,AC

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef __int64 int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

//	z = [2, 30].

int64 ex(int x, int y)	//x^y	,返回int64,为判断爆int32留有余地
{
	int64 ret = 1, now = x;
	for( ; y; y>>=1, now*=now)
	{
		if(y&1)
			ret*=now;
	}
	return ret;
}

int main()
{
	int k;
	while(scanf("%d", &k)!=-1 && k)
	{
		//bug(sqrt((((int64)(1)<<31)-1)*1.0)-1)<<endl;		// max(y) = 46340

		int64 ans = 0;
		int qr = (int)sqrt(k*1.0);
		if(qr*qr == k)		// 最优化剪枝,当z=2时。
		{
			ans += (qr-1)>>1;
		}
		FOR(z, 3, 30)
		{
			for(int x = 1; ; x++)
			{
				int64 t1 = ex(x, z);
				if(t1 + ex(x+1, z) + x*(x+1)*z > k) break;	//可行性剪枝

				//for(int y = x+1;  ; y++)
				//{
				//	int64 f = t1 + ex(y, z) + x*y*z;
				//	if(f > k) break;	//可行性剪枝
				//	else if(f == k)
				//	{
				//		//bug(z);bug(x);bug(y)<<endl;
				//		ans++;
				//		break;	//x、z确定后,f是y的增函数,显然 y是唯一的。	//可行性剪枝
				//	}
				//}

				//int low = x+1, high = 46340;
				//while(low<high)
				//{
				//	int mid = (low+high)>>1;
				//	int64 f = t1 + ex(mid, z) + x*mid*z;
				//	//if(f > k || ex(mid, z)<0 || x*mid*z<0 || f<0) high = mid;
				//	if(f > k || f<0) high = mid;
				//	else if(f < k) low = mid+1;
				//	else if(f == k) { low = mid; break; }
				//}
				////bug(x);bug(z);bug(low)<<endl;
				//if(t1 + ex(low, z) + x*low*z == k)
				//{
				//	ans++;
				//}

				while(low<=high)
				{
					int mid = (low+high)>>1;
					int64 f = t1 + ex(mid, z) + x*mid*z;
					//if(f > k || ex(mid, z)<0 || x*mid*z<0 || f<0) high = mid-1;	//保险点。。
					if(f > k || f<0) high = mid-1;
					else if(f<k) low = mid+1;
					else
					{
						ans++;
						break;
					}
				}
			}
		}
		printf("%I64d\n", ans);
	}
}

3、二分, while(low<high)的写法,wa

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef __int64 int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "

//	z = [2, 30].

int64 ex(int x, int y)	//x^y	,返回int64,为判断爆int32留有余地
{
	int64 ret = 1, now = x;
	for( ; y; y>>=1, now*=now)
	{
		if(y&1)
			ret*=now;
	}
	return ret;
}

int main()
{
	int k;
	while(scanf("%d", &k)!=-1 && k)
	{
		//bug(sqrt((((int64)(1)<<31)-1)*1.0)-1)<<endl;		// max(y) = 46340

		int64 ans = 0;
		int qr = (int)sqrt(k*1.0);
		if(qr*qr == k)		// 最优化剪枝,当z=2时。
		{
			ans += (qr-1)>>1;
		}
		FOR(z, 3, 30)
		{
			for(int x = 1; ; x++)
			{
				int64 t1 = ex(x, z);
				if(t1 + ex(x+1, z) + x*(x+1)*z > k) break;	//可行性剪枝

				//for(int y = x+1;  ; y++)
				//{
				//	int64 f = t1 + ex(y, z) + x*y*z;
				//	if(f > k) break;	//可行性剪枝
				//	else if(f == k)
				//	{
				//		//bug(z);bug(x);bug(y)<<endl;
				//		ans++;
				//		break;	//x、z确定后,f是y的增函数,显然 y是唯一的。	//可行性剪枝
				//	}
				//}

				int low = x+1, high = 46340;
				while(low<high)
				{
					int mid = (low+high)>>1;
					int64 f = t1 + ex(mid, z) + x*mid*z;
					//if(f > k || ex(mid, z)<0 || x*mid*z<0 || f<0) high = mid;
					if(f > k || f<0) high = mid;
					else if(f < k) low = mid+1;
					else if(f == k) { low = mid; break; }
				}
				//bug(x);bug(z);bug(low)<<endl;
				if(t1 + ex(low, z) + x*low*z == k)
				{
					ans++;
				}

				//while(low<=high)
				//{
				//	int mid = (low+high)>>1;
				//	int64 f = t1 + ex(mid, z) + x*mid*z;
				//	//if(f > k || ex(mid, z)<0 || x*mid*z<0 || f<0) high = mid-1;	//保险点。。
				//	if(f > k || f<0) high = mid-1;
				//	else if(f<k) low = mid+1;
				//	else
				//	{
				//		ans++;
				//		break;
				//	}
				//}
			}
		}
		printf("%I64d\n", ans);
	}
}


阅读更多

Very Hard Problem

08-29

It was in the ancient world. ZOJ, the greatest treasure hunter in the world has been lost in the forest for more than 100 hours. Being with no food and no water for such a long time, he was really exhausted this night.nnHe then took out an old map, which was a very strange map. There are many stared positions on the map and it seems those stars are connected by some roads. "I'm sure the treasure is near me, but where is it?", said ZOJ, "If I can't find it, I will be laughed by others."nnSuddenly, ZOJ noticed a slight light. "It was unsual.", said ZOJ and he started looking for the treasure again. After three hours' search, he finally found an entrance. But to enter the entrance, a puzzle should be solved.nnThe puzzle was described like this. Every time, you were given a character in the set '-', '!', '~' and a b-based number. You should take the character as an operator (i.e. '-' changes a number to its opposite number, '!' changes zero to one and non-zero value to zero, '~' takes bitwise operation NOT on all 64 bits of a number) and operates on the number. All you need to do is to print out the result.nnThe puzzle seemed quite simple, but ZOJ was only good at working out the output of the programs written by others, and had no idea about how to solve such a problem. So he turned to you for help.nnInputnnThere are multiple test cases. In each test case, a character ch, a number b and a number n in b-based (2 ≤ b ≤ 16, when b is no less than 10, 'a'..'f' or 'A'..'F' are used) are given in order in one line. ch is assured to be in the set '-', '!', '~', the number (n)b is assured in the range of a signed 64-bit integer. ch, b, n are seperated by one or more spaces. Leading or trailing spaces may also be added to the lines.nnOutputnnFor each test case, print one line, the 10-based result.nnSample Inputnn ~ 10 4n! 10 0n- 16 -FnSample Outputnn-5n1n15

没有更多推荐了,返回首页