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);
}