又見高精度

具體模板我前面的博文中有:大數類模板,我一直都在用這個模板,我認爲比較的好,思路較爲清晰,好吧,再次復出啦。

高精度加法:具體見POJ 2413(有多少個菲波數?),意思不難理解,求區間[a,b](a<=b)中菲波數的個數。

一般思考方法,枚舉,但是題目中說了a<=b<=10^100,相當於100位,枚舉肯定超時,可以換種思路,菲波數是Fib[n]=Fib[n-1]+Fib[n-2],相當於每次都在成倍數增長,所以可以枚舉菲波數,如果在這個區間的話,在枚舉下個菲波數,由於菲波數的值增長特性,應該不會超時,具體見代碼,代碼中addtion(s1,s2)是大數類模板中的高精度相加的模板:

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MAX=150;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int sum1[MAX],sum2[MAX];
bool Comp(string s1,string s2)
{   int len1=s1.length(),len2=s2.length();
    if(len1>len2) return true;
    if(len1==len2)
    {   for(int i=0;i<len1;i++)
            if(s1[i]!=s2[i])
            {   if(s1[i]<s2[i]) return false;
                return true;
            }
        return true;
    }
    return false;
}
int main()
{   string s3,s4;
    while(cin>>s3>>s4)
    {   if(s3=="0"&&s4=="0") break;
        string s,s1="1",s2="1";
        while(!Comp(s1,s3))
        {   s=addtion(s1,s2);
            s2=s1;
            s1=s;
        }    
        int sum=0;
        while(!Comp(s1,s4)||s1==s4)
        {   sum++;
            s=addtion(s1,s2);
            s2=s1;
            s1=s;
        }
        cout<<sum<<endl;
    }
	return 0;
}

當然可以直接先存儲所有的菲波數值,然後直接查找即可,具體見代碼,只寫出修改的位置和main:

const int MAX=500; //開始的時候取小了,直接RE
string Fib[MAX];
.............. 
int main()
{   int n,Case;
    Fib[1]="1",Fib[2]="2";
    for(int i=3;i<MAX;i++)
        Fib[i]=Sub(Fib[i-1],Fib[i-2]);  
    while(cin>>s3>>s4)
    {   if(s3=="0"&&s4=="0") break;
        int sum=0;
        for(int i=1;;i++)
        {   if(Comp(Fib[i],s4)&&Fib[i]!=s4) break;
            if(Comp(Fib[i],s3)) sum++;  
        }  
        cout<<sum<<endl;
    }
    return 0;
} 

題2:NYOJ 513(A+B),這種題目應該都劃分在簡單題中,就是要考慮的情況太多,所以AC率也不高~,我做了好久,用的c++,Java應該很好寫,下面是我的C++代碼,寫得比較的凌亂吧~

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int MAX=1010;
#define max(a,b) a>b?a:b
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int Maxl,sum1[MAX],sum2[MAX];
int Pos(string s)
{   string::size_type pos=s.find('.');
    if(pos!=string::npos) return pos; //要注意第一位爲小數點的情況 
    return -1;
}
int Len(string s)
{   if(Pos(s)!=-1) return s.length()-Pos(s)-1;
    return 0; 
}
string Change(string s) //補充多餘的後導0 
{   int len=Maxl-Len(s);
    for(int i=0;i<len;i++)
        s+='0';
    return s;      
}
string Sub(string s1,string s2)  
{   int i,j; 
    CLR(sum1,0);
    CLR(sum2,0);  
    for(j=0,i=s1.length()-1;i>=0;i--)  
        if(s1[i]!='.') sum1[j++]=(int)s1[i]-'0';  
    for(j=0,i=s2.length()-1;i>=0;i--)  
        if(s2[i]!='.') sum2[j++]=(int)s2[i]-'0';      
    for(i=0;i<MAX;i++)   
    {   sum1[i]+=sum2[i];  
        if(sum1[i]>=10) 
        {   sum1[i]-=10;
            sum1[i+1]++;   
        }
    } 
    string s="";
    for(i=MAX-1;i>=0;i--)
        s+=(char)sum1[i]+'0'; 
    return s;  
}  
int main()
{   string s1,s2;
    while(cin>>s1>>s2)
    {   int i,len1=Pos(s1),len2=Pos(s2); 
        Maxl=max(Len(s1),Len(s2)); //求出最大小數點後面的位數 
        s1=Change(s1),s2=Change(s2);

        string s=Sub(s1,s2); 
        string::iterator it=s.begin(); 
        if(len1!=-1||len2!=-1) s.insert(it+s.length()-Maxl,'.');  //插入小數點 
        
        if(s.find('.')!=string::npos) //全是整數的話不能刪除後導0 
            for(i=s.length()-1;i>=0&&s[i]=='0';i--) s.erase(it+i); 
        
        for(i=0;i<s.length()-1&&s[i]=='0'&&s[i+1]!='.';i++);
        if(i<s.length())
        {   for(;i<s.length()-1;i++)
                cout<<s[i]; 
            if(s[s.length()-1]!='.') cout<<s[s.length()-1];    
        }        
        else cout<<0;
        cout<<endl; 
    }
    return 0;
}        

題3:NYOJ 524(A-B),就是判斷A=B,特別注意的是符號不同時兩個數都爲0的情況,我是把那個NO寫成了No,WA了n次,下面爲我凌亂的代碼,呵呵~~

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int MAX=210;
#define max(a,b) a>b?a:b
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int Maxl,sum1[MAX],sum2[MAX];
bool Judge(string s1,string s2)
{   if(s1[0]=='-'&&s2[0]!='-') return false;
    if(s2[0]=='-'&&s1[0]!='-') return false;
    return true; 
}
int Pos(string s)
{   string::size_type pos=s.find('.');
    if(pos!=string::npos) return pos;
    return -1;
}
int Len(string s)
{   if(Pos(s)!=-1) return s.length()-Pos(s)-1;
    return 0;
}
string Change(string s)
{   int len=Maxl-Len(s);
    for(int i=0;i<len;i++)
        s+='0';
    return s;      
}
void Init(string s1,string s2)
{   CLR(sum1,0);
    CLR(sum2,0);
    for(int i=s1.length()-1,j=0;i>=0;i--)
        if(s1[i]!='.'&&s1[i]!='+'&&s1[i]!='-') sum1[j++]=(int)s1[i]-'0';
    for(int i=s2.length()-1,j=0;i>=0;i--)
        if(s2[i]!='.'&&s2[i]!='+'&&s2[i]!='-') sum2[j++]=(int)s2[i]-'0';       
}    
bool Comp1()
{   int i;
    for(i=MAX-1;i>=0;i--)
        if(sum1[i]!=sum2[i]||sum1[i]!=0||sum2[i]!=0) return false;
    return true;
}    
bool Comp2()
{   for(int i=MAX-1;i>=0;i--)         
        if(sum1[i]!=sum2[i]) return false;
    return true;        
}
int main()
{   string s1,s2;
    while(cin>>s1>>s2)
    {   Maxl=max(Len(s1),Len(s2));
        s1=Change(s1),s2=Change(s2);
        Init(s1,s2);
        if(Judge(s1,s2))
        {   if(Comp2()) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        else
        {   if(Comp1()) cout<<"YES"<<endl;
            else cout<<"NO"<<endl; 
        }
    }
    return 0;
}


 

 

 

 

 



 

 

 

 

 

 

 


 


 


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章