Project Euler 21-25題

第21題

這裏寫圖片描述
題目來源ProjectEuler

這個題定義了一個函數d(x)=divisori ,其中divisorix 的因子且!=x
求小於10,000的所有滿足d(d(a))==aa 的和。
首先求所有數不爲本身的因子的和。如果一個數一個數去分解,複雜度將會是O(nn) 的。但是有一個O(nlogn) 的算法,枚舉1至n的所有數i (其實枚舉到n2 就可以),將[2i,n] 裏所有i 的倍數的標記都加i
然後枚舉1至n的所有數i ,判斷d(d(i))==i 是否成立,若成立則加入答案。

int d[10001];

int main(){
    int n=10000;
    for (int i=1;i<=n;i++){
        for (int j=i*2;j<=n;j+=i){
            d[j]+=i;
        }
    }
    int ans=0;
    for (int i=1;i<=n;i++){
        if (d[i]!=i&&d[i]<=n&&d[d[i]]==i){
            ans+=i;
        }
    }
    cout<<ans<<endl;
    return 0;
}



第22題

這裏寫圖片描述
題目來源ProjectEuler
題中txt地址:https://projecteuler.net/project/resources/p022_names.txt

這個題是給你超過5000個名字(其實是5163個),將所有名字按字典序排序後,求orderiscorei ,其中scorei 定義爲名字中每個字母在26個字母表中的位置。

這道題最最坑爹的地方是,題中沒有說明orderi 是從0開始計數的

我原來想過使用hash的方法用整型表示每個名字的字典序的,但是沒找到很好的hash函數。結果就只能每次直接比較名字的字典序,複雜度變成了O(lengthnlogn) 的了。建議使用編輯器的替換功能將所有的引號和逗號替換成’\n’

struct Name{
    char s[20];
    int sum;
    Name(){sum=0;}
}name[10500];

bool cmp(Name a,Name b){return strcmp(a.s,b.s)<0;}

int main(){
    int cnt=-1;
    freopen("in.txt","r",stdin);
    while(scanf("%s",name[++cnt].s)!=EOF){
        for (int i=0;name[cnt].s[i];i++){
            name[cnt].sum+=name[cnt].s[i]-'A'+1;
        }
    }
    sort(name,name+cnt+1,cmp);
    long long ans=0;
    for (int i=0;i<=cnt;i++){
        ans+=i*name[i].sum;
    }
    cout<<ans<<endl;
    return 0;
}



第23題

這裏寫圖片描述
題目來源ProjectEuler

定義 abundant number爲所有非己因數和大於自己的數。
題目中告知大於28213的所有數都可以表示成兩個abundant number的和。
問所有正數中不能被表示成兩個abundant number的數的和。

使用類似21題的做法,求出小於28213的所有數的非己因數和,將非己因數和大於自身的數加入到vector裏面,做一個O(n2) 的處理,求出這些數兩兩組合的和,打上標記。最後將所有未標記的數加起來。

int num[30000];
vector<int> v;
int isable[30000];

int main(){
    int n=28123;
    memset(num,0,sizeof(num));
    memset(isable,0,sizeof(num));
    for (int i=1;i<=n;i++){
        for (int j=i*2;j<=n;j+=i){
            num[j]+=i;
        }
    }
    for (int i=1;i<=n;i++){
        if (num[i]>i)   {
            v.push_back(i);
        }
    }
    for (int i=0,maxn=v.size();i<maxn;i++){
        for (int j=i;j<maxn&&v[i]+v[j]<=n;j++){
            isable[v[i]+v[j]]=1;
        }
    }
    int ans=0;
    for (int i=1;i<=n;i++){
        if (isable[i]==0)   ans+=i;
    }
    cout<<ans<<endl;
    return 0;
}



第24題

這裏寫圖片描述
題目來源ProjectEuler

這個題是求0123456789這九個數在字典序下的第1,000,000個全排列
利用c++的next_permutation()函數循環999,999次即可。並且這一函數可以作用於char數組。

int main(){
    char num[]={'0','1','2','3','4','5','6','7','8','9','\0'};
    for (int i=1;i<1000000;i++){
        next_permutation(num,num+10);
    }
    cout<<num<<endl;
    return 0;
}



第25題

這裏寫圖片描述
題目來源ProjectEuler

這個題是求第一個達到1000位十進制數的斐波那契項的下標。
1000位也就是10999 數量級的。
利用long double可以記錄104932 的值,雖然有效數字較爲有限,但足夠應付這個題了。其他類型的範圍可參考該博客——桑海的專欄
求斐波那契數列的每一項,直到結果大於10999

int main(){
    long double f1=1,f2=1,f=1;
    int index=2;
    long double maxx=1;
    for (int i=1;i<=999;i++)    maxx*=10;
    for (;f<maxx;){
        index++;
        f=f1+f2;
        f1=f2;f2=f;
    }
    cout<<index<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章