Project Euler 1-25

A. Multiples of 3 and 5

大水题,计算出below n内是3,5倍数的总和

数据较大,只能用求和公式

#include <iostream>
#include <cstdio>
typedef long long ll;
using namespace std;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        ll sum=0;
        ll p;
        p = (n-1)/3;
        sum += (1LL)*3*(p+1)*p/2;
        p = (n-1)/5;
        sum += (1LL)*5*(p+1)*p/2;
        p = (n-1)/15;
        sum -= (1LL)*15*(p+1)*p/2;
        cout<<sum<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 

B.Even Fibonacci numbers

求出n以内所有偶数的总和

所有偶数都是3个一循环出现,序列为0,2,8,34,144...

发现规律E【i】 = 4*E【i-1】+E【i-2】

打表计算

#include <iostream>
#include <cstdio>
typedef long long  ll;
using namespace std;
const int MAXN = 1e3+100;
const ll MAXNN = 4e16;

ll a[MAXN];
ll sum[MAXN];
ll top;

int main()
{
    a[0] = 0;
    a[1] = 2;
    sum[0] = 0;
    sum[1] = 2;
    for(ll i=2;;i++){
        a[i] = 4*a[i-1]+a[i-2];
        top ++;
        sum[i] = sum[i-1]+a[i];
        //cout<<top<<endl;
        if(a[i]>MAXNN)break;
    }
    top+=2;
    //cout<<a[2]<<a[3]<<" "<<a[4]<<endl;
    int T;
    scanf("%d",&T);
    while(T--){
        ll n;
        scanf("%lld",&n);
        int l=0,r=top;
        while(l<r){
            int m = l+(r-l)/2;
            if(a[m]<=n)l = m+1;
            else r = m;
        }

        printf("%lld\n",sum[l-1]);
    }
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 http://digi.tech.qq.com/a/20150526/008620.htm

我发现这个fib时钟挺好玩的

时钟:红色+蓝色

分钟:(绿色+蓝色)*5

 

C. Largest prime factor

求最大质因子

prime打表,昨天打了bc,去求了最大因子,呵呵

#include <iostream>
#include <cstdio>
typedef long long  ll;
using namespace std;
const int MAXN = 1e7+1000;
//const ll MAXNN = 4e16;

int visit[MAXN];
ll p[MAXN];
ll cnt;

void isprime(){
    cnt = 0;
    for(ll i=2;i<MAXN;i++){
        if(!visit[i]){
            p[cnt++] = i;
            for(ll j=i*2;j<MAXN;j+=i){
                visit[j] = 1;
            }
        }
    }
}

int main()
{
    isprime();
    //cout<<p[1]<<endl;
    //cout<<p[2]<<endl;
    int T;
    scanf("%d",&T);
    while(T--){
        ll n;
        scanf("%lld",&n);
       // cout<<n<<endl;
        ll mmax = -1;
        for(ll i=0;i<cnt;i++){
            if(n%p[i]==0){
                mmax = max(mmax,p[i]);
                while(n%p[i]==0)n/=p[i];
            }
        }
        if(n>1){
            mmax = max(mmax,n);
        }
        cout<<mmax<<endl;
       // cout<<n<<endl;

    }

    return 0;
}
View Code

 

 

H.Largest product in a series

求k个连续序列最大值

遍历的时候考虑前一个序列的第一个值是否为0

 

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;

const int MAXN = 1e3+100;
char ts[MAXN];

int main(){

    int T;
    scanf("%d",&T);
    while(T--){
        int n,k;
        scanf("%d%d",&n,&k);
        scanf("%s",ts);
        int len = strlen(ts);
        int mmax=1;
        for(int i=0;i<k;i++)mmax *= (ts[i]-'0');
        int pre = mmax;
        //cout<<pre<<endl;

        for(int i=k;i<len;i++){
            //pre = pre/(ts[i-k]-'0')*(ts[i]-'0');
            if(ts[i-k]-'0'==0){
               pre = 1;
               int s = i-k+1;
               for(int j=1;j<=k;j++){
                    pre *= (ts[s++]-'0');
               }
            }else{
                pre = pre*(ts[i]-'0')/(ts[i-k]-'0');
            }
            mmax = max(mmax,pre);
            //cout<<pre<<endl;
        }
        cout<<mmax<<endl;
    }
    return 0;
}
View Code

I.Special Pythagorean triplet

求构成勾股数的abc,乘积最大

一眼看成求最小,测试数据能过,又傻逼了,改了一个小时看不出,差点要哭

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
typedef long long ll;
using namespace std;


const ll MAXN = 3e3+100;
ll p[MAXN];

int main()
{
    //memset(p,-1,sizeof p);
    for(int i=1;i<MAXN/3;i++){
        for(int j=i+1;j<MAXN/2;j++){
            ll t = (1LL)*i*i + (1LL)*j*j;
            ll x = sqrt(t);
            if(t==x*x&&j<x&&i+j+x<MAXN){
                if(p[i+j+x]==0)
                    p[i+j+x] = (1LL)*i*j*x;
                else
                    p[i+j+x] = max(p[i+j+x],(1LL)*i*j*x);
            }
        }
    }
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        if(p[n]==0){
            cout<<-1<<endl;
            continue;
        }
        cout<<p[n]<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 

L.Highly divisible triangular number

这个挺坑的,反正思路挺清晰的,n的所有因子总数是 (1+a1)*(1+a2)*(1+a3)...(ai为n的质因子)

至于为什么坑了那么久,就是因为打表的时候,我数组我不敢开太大,orz

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>

typedef long long ll;

using namespace std;

const int MAXN = 1e4;
const int MAXNN = 1e6;
int vis[MAXN];
int p[MAXN];
int cnt;
ll s[MAXNN];
ll num[MAXNN];
int top;

void isprime(){
    cnt= 0;
    for(int i=2;i<MAXN;i++){
        if(!vis[i]){
            p[cnt++] = i;
            for(int j=2*i;j<MAXN;j+=i){
                vis[j] = 1;
            }
        }
    }
}

int main()
{
    isprime();
    top = 1;
    for(int i=1;i<MAXNN;i++)s[i] = s[i-1]+i;
    //cout<<s[MAXNN-1]<<endl;
    for(int i=1;i<MAXNN;i++){
        ll t = s[i];
        ll k = 0;
        ll sum=1;
        for(int j=0;j<cnt&&p[j]<=sqrt(t);j++){
            k=0;
            if(t%p[j]==0){
                while(t%p[j]==0){
                    t/=p[j];
                    k++;
                }
                sum *= (k+1);
            }
        }
        if(t>1)sum *= 2;
        num[i] = sum;
        top++;
        if(sum>1000){
            break;

        }
        //cout<<sum<<endl;
    }
   // cout<<top<<endl;
    //cout<<num[top-1]<<endl;
    //cout<<s[top-1]<<endl;

    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        ll ans=-1;
        for(int i=1;i<=top;i++){
            if(num[i]>n){
                ans = s[i];
                //cout<<i<<endl;
                break;
            }
        }
        cout<<ans<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 

 

M.Large sum

大数模板

http://blog.csdn.net/vsooda/article/details/8543351

http://blog.csdn.net/y990041769/article/details/20116995

这些模板都没负数操作的样子。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>

using namespace std;

string sum(string s1,string s2)
{
    if(s1.length()<s2.length())
    {
        string temp=s1;
        s1=s2;
        s2=temp;
    }
    int i,j;
    for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
    {
        s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0));   //注意细节
        if(s1[i]-'0'>=10)
        {
            s1[i]=char((s1[i]-'0')%10+'0');
            if(i) s1[i-1]++;
            else s1='1'+s1;
        }
    }
    return s1;
}


int main()
{
    int n;
    scanf("%d",&n);
    string ts1;
    cin>>ts1;
    for(int i=1;i<n;i++){
        string ts2;
        cin>>ts2;
        ts1 = sum(ts1,ts2);
    }
    for(int i=0;i<10;i++)cout<<ts1[i];
    cout<<endl;
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 

N.Longest Collatz sequence

这题很坑

n可能大于int了(奇数为3*n+1),所以这就要开longlong

一天都不知道错在哪里

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

const int MAXN = 5e6+10;
typedef long long ll;
int a[MAXN],b[MAXN];

int dfs(ll x){
    if(x<MAXN&&a[x]){
        return a[x];
    }
    int sum = 0;
    if(x%2==0){
        sum = dfs(x/2)+1;
    }else{
        sum = dfs(x*3+1)+1;
    }
    if(x<MAXN)a[x] = sum;
    return sum;
}

int main()
{
    a[1]=b[1]=1;
    int mmax = -1;
    int pre = 1;

    for(int i=2;i<MAXN;i++){
        if(!a[i])
            a[i] = dfs(i);
        if(mmax<=a[i]){
            pre = i;
            mmax = a[i];
        }
        b[i] = pre;
    }
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        printf("%d\n",b[n]);
    }
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 

 

O.Lattice paths

简单dp

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll mod = 1e9+7;
const int MAXN = 5e2+10;

ll dp[MAXN][MAXN];

int main(){
   for(int i=1;i<MAXN;i++){
    for(int j=1;j<MAXN;j++){
        if(j==1&&i==1)dp[i][j] = 1;
        else
            dp[i][j] = dp[i-1][j]+dp[i][j-1];
            dp[i][j] %= mod;
        }
    }
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m;
        scanf("%d%d",&n,&m);
        cout<<dp[n+1][m+1]<<endl;
    }
}
View Code

 

P.Power digit sum

字符串操作

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll mod = 1e9+7;
const int MAXN = 1e4+100;

string ts = "1";

ll a[MAXN];

int main(){
    for(int i=1;i<MAXN;i++){
        int len = ts.length();
        int flag = 0;
        ll sum = 0;
        for(int j=len-1;j>=0;j--){
            int t = ts[j]-'0';
            t = t*2+flag;
            ts[j] = char(t%10+'0');
            flag = t/10;
            sum += t%10;
        }
        if(flag){
            ts = "1"+ts;
            sum += 1;
        }
        //cout<<ts<<endl;
        a[i] = sum;
    }
    cout<<ts.length()<<endl;
    cout<<ts<<endl;
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        cout<<a[n]<<endl;
    }
}
View Code

 

 R.Maximum path sum I

简单dp

S.Counting Sundays

计算任意任意区间每月第一天为周七的个数

和省赛一题一模一样,不过好像是求周一的个数,然后我也想当然了,然后第二组测试数据直接出不来。。。

不过学了一个很有用的计算任意时间为周几的 蔡勒公式

http://blog.csdn.net/kumxp/article/details/5185309

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

typedef long long ll;

/*计算任何日期为周几模板*/
int fun(int x,int y,int z){
    if(y<3){
        x-=1;
        y+=12;
    }
    int a = x/100,b = x-100*a;
    int w = a/4 - 2*a+b+b/4+(13*(y+1)/5)+z-1;
    w = (w%7+7)%7;
    return w;
}

int main()
{
    /*for(int i=1;i<13;i++){
        cout<<fun(2016,i,1)<<" ";
    }
    cout<<endl;*/
    int T;
    scanf("%d",&T);
    while(T--){
        ll tx1;int x1,y1,z1;
        ll tx2;int x2,y2,z2;
        scanf("%lld%d%d",&tx1,&y1,&z1);
        scanf("%lld%d%d",&tx2,&y2,&z2);
        x1 = (tx1-1900)%400+1900;
        x2 = (tx2-tx1)+x1;
        int ans = 0;
        for(int i=x1;i<=x2;i++){
            int ret = 0;
            int s = 1,e = 13;
            if(i==x1){
                s = y1;
                if(z1>1)s++;
            }if(i==x2){
                e = y2+1;
            }
            for(int j=s;j<e;j++){
                if(fun(i,j,1)==0)ret++;
            }
            //cout<<ret<<endl;
            ans += ret;
        }
       cout<<ans<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
View Code

 

T.Factorial digit sum

继续套大数相乘模板

 

U.Amicable numbers

打表的时候注意是否会超出得到的数字是否会超出数组范围

第二次犯这个错误了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+1000;
int a[MAXN];
ll b[MAXN];
int main()
{
    //ll sum = 0;
    for(int i=1;i<MAXN;i++){
        int t = i;
        ll cnt = 0;
        for(int j=2;j<=sqrt(t);j++){
            if(t%j==0){
                cnt += j;
                if(j*j!=t)cnt+= t/j;

            }
        }
        cnt++;
        b[i] = cnt;
        if(cnt<i&&b[cnt]==i){a[i] = a[cnt] = 1;}
        else if(cnt>MAXN){
            ll k = 0;
            for(int j=2;j<=sqrt(k);j++){
                if(cnt%j==0){
                    k += j;
                    if(j*j!=cnt)k+= cnt/j;
                }
            }
            k++;
            if(cnt==k)a[i] = 1;
        }
        //cout<<sum<<endl;
    }
    //cout<<b[MAXN-20]<<endl;

    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        ll ret = 0;
        for(int i=1;i<=n;i++){
            if(a[i])ret+= i;
        }
        cout<<ret<<endl;
    }
    return 0;
}
View Code

 

X.Lexicographic permutations

粗略学习了康托展开

排列组合好像非常有用的样子

http://www.cnblogs.com/xianglan/archive/2011/03/07/1976431.html

http://blog.csdn.net/zhongkeli/article/details/6966805

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
ll fac[20];
int sg[20];


int main(){
    ll mult = 1;
    for(int i=1;i<13;i++){
        mult *= i;
        fac[12-i] = mult;
    }
    int T;
    string ts;
    scanf("%d",&T);
    while(T--){
        ts = "abcdefghijklm";
        memset(sg,0,sizeof sg);
        ll n;
        scanf("%lld",&n);
        n--;
        for(int i=0;i<12;i++){
            sg[i] = n/fac[i];
            n -= sg[i]*fac[i];
        }
        /*for(int i=0;i<12;i++){
            cout<<sg[i]<<" ";
        }
        cout<<endl;*/
        for(int i=0;i<12;i++){
            swap(ts[i],ts[i+sg[i]]);
            sort(ts.begin()+i+1,ts.end());
        }
        cout<<ts<<endl;
     }
}
View Code

 

Y.N-digit Fibonacci number

求第一次出现5000-digit fibonacci的下标

这题应该能用字符串的大数操作的样子

学习了一种公式的方法

fib数列如果n较大时,满足an/an+1 = 0.618:1

则an*phi = an,phi=(1+sqrt(5))/2

ox  = (1-sqrt(5))/2

可以推出an的通式 an = 1/(sqrt(5))*(phi-ox)^n

则len_dig = (int)(nlog10(phi)-log10(5)/2+1)

呵呵,继续学习了fib

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

typedef long long ll;
const int MAXN = 5e3+10;
const int MAXNN = 3e4+100;
double golden = (1+sqrt(5))/2;
int a[MAXN];
int len_fib(ll n){
    return (int)(n*log10(golden) - log10(5)/2+1);
}


int main(){
    //cout<<len_fib(17)<<endl;
    //ll k = 0;
    a[1] = 1;
    for(int i=2;i<MAXN;i++){
        int l = 1,r = MAXNN;
        while(l<r){
            int m = l+(r-l)/2;
            if(len_fib(m)<i)l = m+1;
            else r = m;
        }
        a[i] = l;
    }
    /*cout<<a[2]<<endl;
    cout<<a[3]<<endl;
    cout<<a[5000]<<endl;
    cout<<k<<endl;*/
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        cout<<a[n]<<endl;
    }
    return 0;
}
View Code

 

posted @ 2016-07-25 01:02  iEdson  阅读(228)  评论(0编辑  收藏  举报