题目链接: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;
}