ICPC2017网络赛(乌鲁木齐)E: Half-consecutive Numbers (大数)

来源:互联网 发布:mac中如何切换输入法 编辑:程序博客网 时间:2024/05/10 15:05

E: Half-consecutive Numbers time

 limit 2000ms memory limit 131072KB 


The numbers 1, 3, 6, 10, 15, 21, 28, 36, 45 and t = i(i +1), are called halfconsecutive. For given N, find the smallest r which is no smaller than N such that t is square.
 i 2
 
 1
 r
Input Format The input contains multiple test cases. The first line of a multiple input is an integer T followed by T input lines. Each line contains an integer N (1 ≤ N ≤ 10 ). Output Format For each test case, output the case number first. Then for given N, output the smallest r. If this half-consecutive number does not exist, output −1. Sample Input
4 1 2 9 50
Sample Output
Case #1: 1 Case #2: 8 Case #3: 49 Case #4: 288

【题意】:

找到这样的i,使得i*(i+1)=2*k^2。其中k为任意整数,i为整数。

然后输入n,输出不小于n的这个i。

【解析】:

先找到了规律,对于所有满足条件的i,对应的k,排成一个数列,那么数列满足:

F[1]=1;

F[2]=8;

F[t]=F[t-1]*6 - F[i-2];

把这个F数组全打表出来,总共就几十个。再由他解出i;

说实话这个规律看了好久才看出来。。。。。

提前打表出这些满足条件的i存起来。

【代码】:

AC代码:

#include <stdio.h>long long a[50]={1,8,49,288,1681,9800,57121,332928,1940449,11309768,65918161,384199200,2239277041,13051463048,76069501249,443365544448,2584123765441,15061377048200,87784138523761,511643454094368,2982076586042449,17380816062160328,-1};int main(){int T,r=1;long long n;scanf("%lld",&T);while(T--){scanf("%lld",&n);int i;for(i=0;a[i]!=-1;i++){if(a[i]>=n)break;}printf("Case #%d: %lld\n",r++,a[i]);}return 0;}

打表代码:

#include <stdio.h>#include <math.h>  #include <stdlib.h>  #include <string.h>  #include <time.h>  #include <iostream>  #include <algorithm> #include <queue>   #include <stack> using namespace std;typedef long long ll;const ll MAX=1e17;const int M=1e8;//亿进制typedef queue<ll> BigNum;    BigNum getnum(ll num)    {        BigNum q;        while(num)        {            q.push(num%M);            num/=M;        }        return q;    }    void out(BigNum q)//递归输出队列大数        {          if(q.size()==1){              printf("%lld",q.front());               return;        }          ll num=q.front(); q.pop();          out(q);          printf("%08lld",num);    }  BigNum operator+(BigNum q1,BigNum q2)//加  {              BigNum sum;            ll flag=0;//进位             while(!q1.empty()||!q2.empty())            {                  int num1=0,num2=0;                  if(!q1.empty()){                      num1=q1.front();                      q1.pop();                  }                  if(!q2.empty()){                      num2=q2.front();                      q2.pop();                  }                  sum.push(flag+(num1+num2)%M);                  flag=(num1+num2)/M;            }              if(flag)                sum.push(flag);            return sum;        }  BigNum operator*(BigNum q1,BigNum q2)//大数乘大数          {              BigNum ans;              ll k=0;      while(!q2.empty())//模拟手工运算          {          ll n=q2.front();  q2.pop();          BigNum temp,re=q1;//re暂存q1                  for(int i=0;i<k;i++)                      temp.push(0);  //后置0                 k++;                  ll flag=0;//进位                  while(!re.empty())                  {              temp.push(flag+(n*re.front())%M);                      flag=(n*re.front())/M;                      re.pop();                  }                  if(flag)                      temp.push(flag);                  ans=ans+temp;//累加              }              return ans;          }          BigNum operator/(BigNum q,ll m)//大数q整除以m(注,m+M<ll)    {            stack<ll> s,ans;          while(!q.empty()){  //压入栈             s.push(q.front());                q.pop();            }        ll flag=0;//flag移位             while(!s.empty())            {            ll top=s.top()+flag*M;            if(top>=m||!ans.empty())//排除最高位是0                 ans.push(top/m);            flag=top%m;            s.pop();        }//最后的flag为余数        while(!ans.empty()){            q.push(ans.top());            ans.pop();        }        if(q.empty())q.push(0);        return q;        }  int mycmp(BigNum q1,BigNum q2)  {      if(q1.size()==q2.size())      {          ll num1,num2,flag=0;          while(!q1.empty())          {              num1=q1.front();q1.pop();              num2=q2.front();q2.pop();              if(num1!=num2)                  flag=num1-num2;          }          return flag;      }      return q1.size()-q2.size();  }  BigNum operator*(BigNum q1,ll m)//大数乘int m         {              BigNum ans;            ll flag=0;//进位             while(!q1.empty())            {                  ll num=q1.front();              q1.pop();                 ans.push((m*num+flag)%M);                  flag=(m*num+flag)/M;          }              if(flag)                ans.push(flag);            return ans;        }       BigNum operator-(BigNum q1,BigNum q2)//q1-q2(注!仅限q1>q2)  {      BigNum less;      if(mycmp(q1,q2)<0){          BigNum a=q1;q1=q2;q2=a;      }        while(!q1.empty())      {                  int num1=0,num2=0;          num1=q1.front();          q1.pop();          if(!q2.empty()){              num2=q2.front();              q2.pop();          }          if(num1<num2){              q1.front()-=1;              num1+=M;//从q1高位借1,当M          }          less.push(num1-num2);      }      return less;  }      BigNum f(BigNum i){return i*i+i;}int main(){ll ans=0;BigNum F[50];F[0]=getnum(0);F[1]=getnum(1);for(int i=2;i<40;i++){F[i]=F[i-1]*6-F[i-2];}for(int i=1;i<40;i++){BigNum k=F[i]*F[i];BigNum l=getnum(1),r=getnum(100000000000000000);while(mycmp(l,r)<0)//二分查找解i {BigNum mid=(l+r)/2;if(mycmp(f(mid),k*2)>=0)r=mid;else l=mid+getnum(1);}if(mycmp(f(l),k*2)==0){ans++;out(l);printf(",\n");}}printf("%lld\n",ans);}


阅读全文
0 0
原创粉丝点击