• 题解 UVA10213 【How Many Pieces of Land ?】


    题目链接:Link

    Solution

    紫书上的思路很容易理解,但时间复杂度太高。在网上搜了半天终于在维基百科上搜到了O(1)算法。
    以下证明过程摘自维基百科:

    即答案为 (n*n*n*n-6*n*n*n+23*n*n-18*n+24)/24

    由于 0≤n≤2^31,需要高精度。

    c++代码如下:

    #include<iostream>
    #ifndef BIGINT
    #define BIGINT
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    template<class T_queue>
    struct Node_queue_for_bigint
    {
    	T_queue num;
    	Node_queue_for_bigint *next;
    	Node_queue_for_bigint()
    	{
    		next=0;
    	}
    };
    template<class a_queue>
    struct queue_for_bigint
    {
    	Node_queue_for_bigint<a_queue> *head,*tail,*L;
    	bool isn;
    	int SIZE_queue;
    	void beginning()
    	{
    		head=tail=L=0;
    		isn=0;
    		head=tail=new Node_queue_for_bigint<a_queue>;
    		tail->next=head;
    		SIZE_queue=0;
    		isn=1;
    	}
    	queue_for_bigint()
    	{
    		beginning();
    	}
    	~queue_for_bigint()
    	{
    		Node_queue_for_bigint<a_queue> *p=head,*tp;
    		p=p->next;
    		while(p!=head)
    		{
    			tp=p->next;
    			delete p;
    			p=tp;
    		}
    	}
    	bool push(a_queue s)
    	{
    		SIZE_queue++;
    		tail->num=s;
    		if(tail->next==head)
    		{
    			tail->next=new Node_queue_for_bigint<a_queue>;
    			tail->next->next=head;
    			L=tail;
    			tail=tail->next;
    			return 1;
    		}
    		L=tail;
    		tail=tail->next;
    		return 0;
    	}
    	bool pop()
    	{
    		if(head==tail) return 1;
    		head=head->next;
    		SIZE_queue--;
    		return 0;
    	} 
    	a_queue& front()
    	{
    		return head->num;
    	} 
    	a_queue& back()
    	{
    		return L->num;
    	}
    	int size()
    	{
    		return SIZE_queue;
    	}
    	void clear()
    	{
    		SIZE_queue=0;
    		tail=head;
    	}
    	bool operator=(queue_for_bigint<a_queue>b)
    	{
    		if(!isn)
    		{
    			this->beginning();
    			isn=1;
    		}
    		this->clear();
    		Node_queue_for_bigint<a_queue> *p=b.head;
    		while(p!=b.tail)
    		{
    			this->push(p->num);
    			p=p->next;
    		}
    		return 0;
    	}
    };
    int CacheSize=25;//try to use the cache
    queue_for_bigint<char*> Mems;
    queue_for_bigint<int> q;
    queue_for_bigint<char> cache;
    struct BigInt
    {
    	char f:4,nAn:4;
    	std::vector<int> num;
    	static const int base=100000000;
    	BigInt()
    	{
    		f=0;
    		nAn=0;
    		num.push_back(0);
    	}
    	template<class TYPE>
    	BigInt(TYPE V)
    	{
    		f=nAn=0;
    		*this=V;
    	}
    	void format()
    	{
    		while(num.size()>1&&num[num.size()-1]<=0) num.erase(num.end()-1);
    		if(num.size()==1&&num[0]==0) f=0;
    		if(num.size()==0) num.push_back(0),f=nAn=0;
    	}
    	//Input and Output
    	char* c_str()
    	{
    		char *p,*ptr;
    		if(!nAn)
    		{
    			p=new char[num.size()*8+16];
    			ptr=p;
    			memset(p,0,num.size()*8+16);
    			if(f) sprintf(p,"-"),p++;
    			sprintf(p,"%d",num[num.size()-1]);
    			for(int i=num.size()-2;i>=0;i--)
    			{
    				while(*p) p++;
    				sprintf(p,"%08d",num[i]);
    			}
    		}
    		else
    		{
    			p=new char[5];
    			sprintf(p,"nan");
    		}
    		Mems.push(ptr);
    		return ptr;
    	}
    	std::string str()
    	{
    		std::string ss=c_str();
    		return ss;
    	}
    	BigInt operator=(char* s)
    	{
    		f=0;
    		if(s==0) return BigInt();
    		if(*s=='-')
    		{
    			f=1;
    			s++;
    		}
    		int len=strlen(s),add=0,i,t;
    		num.resize(len/8+1);
    		char *p=s+len-1;
    		while(p-7>=s)
    		{
    			t=0;
    			for(i=-7;i<=0;i++)
    				if(p+i>=s) t=t*10+*(p+i)-'0';
    			p-=8;
    			num[add++]=t;
    		}
    		if(p>=s)
    		{
    			t=0;
    			while(s<=p) t=t*10+*(s++)-'0';
    			num[add++]=t;
    		}
    		while(num.size()>add) num.erase(num.end()-1);
    		return *this;
    	}
    	BigInt operator=(std::string ss)
    	{
    		char *s=&ss[0];
    		f=0;
    		if(s==0) return BigInt();
    		if(*s=='-')
    		{
    			f=1;
    			s++;
    		}
    		int len=strlen(s),add=0,i,t;
    		num.resize(len/8+1);
    		char *p=s+len-1;
    		while(p>=s)
    		{
    			t=0;
    			for(i=-7;i<=0;i++)
    				if(p+i>=s) t=t*10+*(p+i)-'0';
    			p-=8;
    			num[add++]=t;
    		}
    		while(num.size()>add) num.erase(num.end()-1);
    		return *this;
    	}
    	BigInt operator=(int v)
    	{
    		f=0;
    		if(v<0)
    		{
    			f=1;
    			v=-v;
    		}
    		q.clear();
    		if(v==0) q.push(0);
    		else
    			while(v>0)
    			{
    				q.push(v%base);
    				v/=base;
    			}
    		num.resize(q.size());
    		for(int i=0;q.size()>0;i++)
    		{
    			num[i]=q.front();
    			q.pop();
    		}
    		return *this;
    	}
    	BigInt operator=(unsigned int v)
    	{
    		f=0;
    		q.clear();
    		if(v==0) q.push(0);
    		else
    			while(v>0)
    			{
    				q.push(v%base);
    				v/=base;
    			}
    		num.resize(q.size());
    		for(int i=0;q.size()>0;i++)
    		{
    			num[i]=q.front();
    			q.pop();
    		}
    		return *this;
    	}
    	BigInt operator=(long long v)
    	{
    		f=0;
    		if(v<0)
    		{
    			f=1;
    			v=-v;
    		}
    		q.clear();
    		if(v==0) q.push(0);
    		else
    			while(v>0)
    			{
    				q.push(v%base);
    				v/=base;
    			}
    		num.resize(q.size());
    		for(int i=0;q.size()>0;i++)
    		{
    			num[i]=q.front();
    			q.pop();
    		}
    		return *this;
    	}
    	BigInt operator=(unsigned long long v)
    	{
    		f=0;
    		q.clear();
    		if(v==0) q.push(0);
    		else
    			while(v>0)
    			{
    				q.push(v%base);
    				v/=base;
    			}
    		num.resize(q.size());
    		for(int i=0;q.size()>0;i++)
    		{
    			num[i]=q.front();
    			q.pop();
    		}
    		return *this;
    	}
    	//====================/
    	//In-situ operation
    	BigInt operator++()
    	{
    		format();
    		if(!f)
    		{
    			num[0]++;
    			int i=1;
    			while(i<num.size()&&num[i-1]>=base)
    				num[i]++,num[i-1]-=base,i++;
    			if(num[i-1]>=base)
    				num.push_back(1),num[i-1]-=base;
    		}
    		else
    		{
    			num[0]--;
    			int i=1;
    			while(i<num.size()&&num[i-1]<0)
    				num[i]--,num[i-1]+=base,i++;
    			format();
    		}
    		return *this;
    	}
    	BigInt operator++(int)
    	{
    		format();
    		BigInt t=*this;
    		if(!f)
    		{
    			num[0]++;
    			int i=1;
    			while(i<num.size()&&num[i-1]>=base)
    				num[i]++,num[i-1]-=base,i++;
    			if(num[i-1]>=base)
    				num.push_back(1),num[i-1]-=base;
    		}
    		else
    		{
    			num[0]--;
    			int i=1;
    			while(i<num.size()&&num[i-1]<0)
    				num[i]--,num[i-1]+=base,i++;
    			format();
    		}
    		return t;
    	}
    	BigInt operator--()
    	{
    		format();
    		if(!f)
    		{
    			num[0]--;
    			int i=1;
    			while(i<num.size()&&num[i-1]<0)
    				num[i]--,num[i-1]+=base,i++;
    			if(num[i-1]<0)
    				*this=-1;
    			format();
    		}
    		else
    		{
    			num[0]++;
    			int i=1;
    			while(i<num.size()&&num[i-1]>=base)
    				num[i]++,num[i-1]-=base,i++;
    			if(num[i-1]>=base)
    				num.push_back(1),num[i-1]-=base;
    		}
    		return *this;
    	}
    	BigInt operator--(int)
    	{
    		format();
    		BigInt t=*this;
    		if(!f)
    		{
    			num[0]--;
    			int i=1;
    			while(i<num.size()&&num[i-1]<0)
    				num[i]--,num[i-1]+=base,i++;
    			if(num[i-1]<0)
    				*this=-1;
    			format();
    		}
    		else
    		{
    			num[0]++;
    			int i=1;
    			while(i<num.size()&&num[i-1]>=base)
    				num[i]++,num[i-1]-=base,i++;
    			if(num[i-1]>=base)
    				num.push_back(1),num[i-1]-=base;
    		}
    		return t;
    	}
    	//=====================/
    };
    //compare operations
    bool operator<(BigInt a,BigInt b)
    {
    	a.format();
    	b.format();
    	if(a.f!=b.f) return a.f>b.f;
    	if(a.f==0)
    	{
    		if(a.num.size()<b.num.size()) return 1;
    		else if(a.num.size()>b.num.size()) return 0;
    		for(int i=a.num.size()-1;i>=0;i--)
    			if(a.num[i]<b.num[i]) return 1;
    			else if(a.num[i]>b.num[i]) return 0;
    	}
    	else
    	{
    		if(a.num.size()>b.num.size()) return 1;
    		else if(a.num.size()<b.num.size()) return 0;
    		for(int i=a.num.size()-1;i>=0;i--)
    			if(a.num[i]>b.num[i]) return 1;
    			else if(a.num[i]<b.num[i]) return 0;
    	}
    	return 0;
    }
    bool operator==(BigInt a,BigInt b)
    {
    	a.format();
    	b.format();
    	if(a.f!=b.f) return 0;
    	if(a.num.size()!=b.num.size()) return 0;
    	for(int i=a.num.size()-1;i>=0;i--)
    		if(a.num[i]!=b.num[i]) return 0;
    	return 1;
    }
    bool operator!=(BigInt a,BigInt b)
    {
    	a.format();
    	b.format();
    	if(a.f!=b.f) return 1;
    	if(a.num.size()!=b.num.size()) return 1;
    	for(int i=a.num.size()-1;i>=0;i--)
    		if(a.num[i]!=b.num[i]) return 1;
    	return 0;
    }
    bool operator>(BigInt a,BigInt b)
    {
    	a.format();
    	b.format();
    	if(a.f!=b.f) return a.f<b.f;
    	if(a.f==0)
    	{
    		if(a.num.size()>b.num.size()) return 1;
    		else if(a.num.size()<b.num.size()) return 0;
    		for(int i=a.num.size()-1;i>=0;i--)
    			if(a.num[i]>b.num[i]) return 1;
    			else if(a.num[i]<b.num[i]) return 0;
    	}
    	else
    	{
    		if(a.num.size()<b.num.size()) return 1;
    		else if(a.num.size()>b.num.size()) return 0;
    		for(int i=a.num.size()-1;i>=0;i--)
    			if(a.num[i]<b.num[i]) return 1;
    			else if(a.num[i]>b.num[i]) return 0;
    	}
    	return 0;
    }
    bool operator<=(const BigInt &a,const BigInt &b){return (a<b||a==b);}
    bool operator>=(const BigInt &a,const BigInt &b){return (a>b||a==b);}
    //=================/
    //maths operations
    BigInt operator+(BigInt a,BigInt b);
    BigInt operator-(BigInt a,BigInt b);
    BigInt operator*(BigInt a,BigInt b);
    BigInt operator/(BigInt a,BigInt b);
    void BigInt_add		(BigInt &a,BigInt &b,BigInt &c);
    void BigInt_minus	(BigInt &a,BigInt &b,BigInt &c);
    void BigInt_times	(BigInt &a,BigInt &b,BigInt &c);
    void BigInt_divide	(BigInt &a,BigInt &b,BigInt &c);
    void BigInt_add(BigInt &a,BigInt &b,BigInt &c)
    {
    	a.format();
    	b.format();
    	c.nAn=(a.nAn==1||b.nAn==1);
    	if(c.nAn) return;
    	if(a.f)
    	{
    		if(b.f)
    		{
    			a.f=b.f=0;
    			BigInt_add(a,b,c);
    			a.f=b.f=c.f=1;
    			return;
    		}
    		else
    		{
    			a.f=0;
    			BigInt_minus(b,a,c);
    			a.f=1;
    			return;
    		}
    	}
    	else if(b.f)
    	{
    		b.f=0;
    		BigInt_minus(a,b,c);
    		b.f=1;
    		return;
    	}
    	int t=0,t2=std::max(a.num.size(),b.num.size())+1;
    	c.num.resize(t2);
    	memset(&c.num[0],0,t2*4);
    	for(int i=0;i<t2;i++)
    	{
    		if(i<a.num.size()) t+=a.num[i];
    		if(i<b.num.size()) t+=b.num[i];
    		c.num[i]=t%BigInt::base;
    		t/=BigInt::base;
    	}
    	c.format();
    }
    void BigInt_minus(BigInt &a,BigInt &b,BigInt &c)
    {
    	a.format();
    	b.format();
    	c.nAn=(a.nAn==1||b.nAn==1);
    	if(c.nAn) return;
    	if(a.f)
    	{
    		if(b.f)
    		{
    			a.f=b.f=0;
    			BigInt_minus(b,a,c);
    			a.f=b.f=1;
    			return;
    		}
    		else
    		{
    			a.f=0;
    			BigInt_add(a,b,c);
    			a.f=c.f=1;
    			return;
    		}
    	}
    	else if(b.f)
    	{
    		b.f=0;
    		BigInt_add(a,b,c);
    		b.f=1;
    		return;
    	}
    	if(a<b)
    	{
    		BigInt_minus(b,a,c);
    		c.f=1;
    		return;
    	}
    	c=a;
    	int z=0,k;
    	for(int i=0;i<b.num.size();i++)
    	{
    		c.num[i]=c.num[i]-b.num[i];
    		if(c.num[i]<0)
    		{
    			c.num[i]+=BigInt::base;
    			z=1;
    		}
    		else z=0;
    		k=i+1;
    		while(z&&k<c.num.size())
    		{
    			c.num[k]--;
    			if(c.num[k]<0)
    			{
    				z=1;
    				c.num[k]+BigInt::base;
    			}
    			else z=0;
    			k++;
    		}
    	}
    	c.format();
    }
    void BigInt_times(BigInt &a,BigInt &b,BigInt &c)
    {
    	a.format();
    	b.format();
    	c.nAn=(a.nAn==1||b.nAn==1);
    	if(c.nAn) return;
    	c.num.resize(a.num.size()+b.num.size());
    	memset(&c.num[0],0,(a.num.size()+b.num.size())*4);
    	int i,j,k,I,J;
    	long long t;
    	int *A,*B,*C,As=a.num.size(),Bs=b.num.size();
    	A=&(a.num[0]);
    	B=&(b.num[0]);
    	C=&(c.num[0]);
    	for(i=0;i<As;i+=CacheSize)
    		for(j=0;j<Bs;j+=CacheSize)
    			for(I=i;I<i+CacheSize&&I<As;I++)
    				for(J=j;J<j+CacheSize&&J<Bs;J++)
    				{
    					t=(long long)A[I]*B[J];
    					t=t+C[I+J];
    					C[I+J]=t%BigInt::base;
    					k=I+J+1;
    					t/=BigInt::base;
    					while(t>0)
    					{
    						t=t+C[k];
    						C[k++]=t%BigInt::base;
    						t=t/BigInt::base;
    					}
    				}
    	c.f=(a.f!=b.f);
    	c.format();
    }
    void BigInt_divide(BigInt &a,BigInt &b,BigInt &c)
    {
    	BigInt t;
    	a.format();
    	b.format();
    	bool af=a.f,bf=b.f;
    	a.f=b.f=0;
    	if(a<b)
    	{
    		c=BigInt();
    		return;
    	}
    	c.nAn=(a.nAn==1||b.nAn==1||(b.num.size()==1&&b.num[0]==0));
    	c.f=0;
    	if(c.nAn) return;
    	c.num.resize(a.num.size()-b.num.size()+1,0);
    	int L,R;
    	for(int i=c.num.size()-1;i>=0;i--)
    	{
    		L=0;
    		R=a.base-1;
    		while(L+1<R)
    		{
    			c.num[i]=(L+R)/2;
    			BigInt_times(b,c,t);
    			if(t>a) R=(L+R)/2;
    			else L=(L+R)/2;
    		}
    		c.num[i]=L;
    	}
    	c.format();
    	a.f=af;
    	b.f=bf;
    	c.f=(af!=bf);
    }
    BigInt operator+(BigInt a,BigInt b)
    {
    	BigInt t;
    	BigInt_add(a,b,t);
    	return t;
    }
    BigInt operator+=(BigInt &a,BigInt b)
    {
    	BigInt t;
    	BigInt_add(a,b,t);
    	return a=t;
    }
    BigInt operator-(BigInt a,BigInt b)
    {
    	BigInt t;
    	BigInt_minus(a,b,t);
    	return t;
    }
    BigInt operator-=(BigInt &a,BigInt b)
    {
    	BigInt t;
    	BigInt_minus(a,b,t);
    	return a=t;
    }
    BigInt operator*(BigInt a,BigInt b)
    {
    	BigInt t;
    	BigInt_times(a,b,t);
    	return t;
    }
    BigInt operator*=(BigInt &a,BigInt b)
    {
    	BigInt t;
    	BigInt_times(a,b,t);
    	return a=t;
    }
    BigInt operator/(BigInt a,BigInt b)
    {
    	BigInt c;
    	BigInt_divide(a,b,c);
    	return c;
    }
    BigInt operator/=(BigInt &a,BigInt b)
    {
    	BigInt c;
    	BigInt_divide(a,b,c);
    	return a=c;
    }
    BigInt operator%(BigInt a,BigInt b)
    {
    	BigInt t1,t2;
    	BigInt_divide(a,b,t1);
    	BigInt_times(t1,b,t2);
    	BigInt_minus(a,t2,t1);
    	return t1;
    }
    BigInt operator%=(BigInt &a,BigInt b)
    {
    	BigInt t1,t2;
    	BigInt_divide(a,b,t1);
    	BigInt_times(t1,b,t2);
    	BigInt_minus(a,t2,t1);
    	return a=t1;
    }
    void free_pointers()//Releasing temporary memory
    {
    	while(Mems.size()>0)
    	{
    		delete[] Mems.front();
    		Mems.pop();
    	}
    }
    //======================/
    #endif
    
    //stream input and output
    #ifdef _GLIBCXX_OSTREAM
    std::ostream& operator<<(std::ostream& str,BigInt n)
    {
    	n.format();
    	if(n.nAn) str<<"nan";
    	else
    		str<<n.c_str();
    	return str;
    }
    #endif
    
    #ifdef _GLIBCXX_ISTREAM
    std::istream& operator>>(std::istream& str,BigInt &n)
    {
    	cache.clear();
    	while(!str.eof()&&!(str.peek()=='-'||(str.peek()>='0'&&str.peek()<='9')))
    		str.get();
    	bool flag=0;
    	while(!str.eof()&&str.peek()=='-') flag=!flag,str.get();
    	if(flag) cache.push('-');
    	while(!str.eof()&&str.peek()>='0'&&str.peek()<='9') cache.push(str.get());
    	char *p=new char[cache.size()+1],*t;
    	memset(p,0,cache.size()+1);
    	t=p;
    	while(cache.size()>0) *t++=cache.front(),cache.pop();
    	n=p;
    	delete[] p;
    	return str;
    }
    #endif//以上的高精度代码摘自我自己编写的一个高精度库。
    using namespace std;
    int T;
    BigInt n,res;
    int main()
    {
    #ifdef local
    	freopen("pro.in","r",stdin);
    #endif
    	cin>>T;
    	while(T-->0)
    	{
    		cin>>n;
    		res=(n*(n*(n*(n-6)+23)-18)+24)/24;
            /*
            优化计算,原式为
            (n*n*n*n-6*n*n*n+23*n*n-18*n+24)/24
            */
    		cout<<res<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    使用ACEGI搭建权限系统:第三部分
    分支在版本树中的应用(使用subversion)
    acegi安全框架使用:第二部分
    错误数据导致java.lang.IllegalArgumentException:Unsupported configuration attributes
    移动中间件和wap网关的比较
    3年后,又回到了.net阵营
    android中listView的几点总结
    oracle相关分布式数据解决方案
    ajax实现用户名存在校验
    使用template method模式简化android列表页面
  • 原文地址:https://www.cnblogs.com/happyZYM/p/11380000.html
Copyright © 2020-2023  润新知