西山居初赛二 总结

hdu 4548 美素数

  用线性筛法筛选出10^6的素数,然后预处理统计下.. O(1)就能得到结果了.

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<algorithm>

using namespace std;



const int N = (int)1e6+10;



bool vis[N];

int p[N], sum[N];

void GetPrime(){

    memset(vis,0,sizeof(0));

    vis[1] = 1;

    int cnt = 0;

    for(int i = 2; i < N; i++){

        if( !vis[i] ) p[cnt++] = i;

        for(int j = 0; (j<cnt)&&(p[j]*i<N); j++){

            vis[ p[j]*i ] = 1;

            if( i%p[j] == 0 )break;

        }

    }

}

int Dight(int x){

    int s = 0;

    while(x) s+=x%10, x /= 10;

    return s;

}

void init(){

    GetPrime();

    sum[0] = sum[1] = 0;

    for(int i = 2; i < N; i++){

        sum[i] = sum[i-1];    

        if( !vis[i] && !vis[ Dight(i) ] ) sum[i]++; 

    }

}

int main(){

    init();

    int T;

    scanf("%d", &T);

    for(int Case = 1; Case <= T; Case++ ){

        int a, b;

        scanf("%d%d", &a,&b);

        printf("Case #%d: %d\n", Case, sum[b] - sum[a-1] );    

    }

    return 0;

}
View Code

 

hdu 4549 M斐波那契数列

  直接搞显然不行, 没有线性关系. 简单推导下有,  a, b, a^1*b^1, a^1*b^2 .... 可以知道a,b的幂满足Fib, 然后构造矩阵快速幂...就好了.还需要个性质: A^X = A^( X mod Eular(M) ) ( mod M ) .

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<algorithm>

using namespace std;



typedef long long LL;

const int mod = (int)1e9+7;



struct Matrix{

    LL mat[2][2];

    void zero(){memset(mat,0,sizeof(mat)); }

    void unit(){zero();mat[0][0]=mat[1][1]=1;}    

}A, T;



void init_Matrix(){

    A.zero(); T.zero();

    A.mat[0][0]=A.mat[1][0]=1;

    T.mat[0][1]=T.mat[1][0]=T.mat[1][1]=1;

}

void print(Matrix a){

    printf("Matrix:\n");

    for(int i = 0; i < 2; i++){

        for(int j = 0; j < 2; j++)    

            printf("%d ", (int)a.mat[i][j]);

        puts("");

    }

}

Matrix mult(Matrix a, Matrix b){

    Matrix c; c.zero();

    for(int i = 0; i < 2; i++)

        for(int j = 0; j < 2; j++)

            for(int k = 0; k < 2; k++)

                c.mat[i][k]=(c.mat[i][k]+a.mat[i][j]*b.mat[j][k])%(mod-1);

    return c;

}

Matrix Pow(Matrix x,int n){

    Matrix c; c.unit();

    while( n ){

        if(n&1) c = mult(x,c);

        x = mult(x,x);

        n >>= 1;

    }

    return c;

}

LL Fib(int n){

    init_Matrix();

    A = mult( Pow(T,n-1), A );        

    return A.mat[0][0];

}

LL pow( LL x, int n ){

    LL c = 1;

    while(n){

        if(n&1) c = c*x%mod;

        x = x*x%mod;

        n >>= 1;

    }

    return c;

}

int main(){

    int a, b, n;    

    while( scanf("%d%d%d",&a,&b,&n) != EOF){

        if( n < 2 ){

            if( n == 0 ) printf("%d\n", a);

            else printf("%d\n", b);

        }                

        else{

            LL n1 = Fib( n-1 ), n2 = Fib( n );

    //        printf("n1 = %d, n2 = %d\n", (int)n1, (int)n2 );    

            LL ans = pow(a,n1)*pow(b,n2)%mod;    

            printf("%d\n", (int)ans );    

        }    

    }    

    return 0;

}
View Code

 

hdu 4550卡片游戏

  和波神讨论了好久...有0的情况好恶心. 最后邪恶的处理第一次出现0 的情况. 主要是出现了0, 则此时,在之后选定一个最小非0的数放在前面必定最优. 其他情况就是大的放后,小的放前面.....稀里哗啦写了好多..  A掉了后看到别人代码好短- - .....才发现好多地方做了无用工.......

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<string>

#include<algorithm>

using namespace std;



const int N = 110;



char s[N];

string t;

int len;

// S( i, len-1 )

void gao( int i ){

        char tm = '9'+10; 

        int pos = -1, cnt = 0;      

        for(int j = i; j < len; j++){    

            if( (s[j]!='0') && (tm>=s[j]) ) tm = s[j], pos = j;    

        }        

        if( (pos==-1) || ( (t[0]!='0')&&(s[pos]>t[0]))){

            for(int j = i; j < len; j++) t = t+s[j];    

        }

        else{

            for(int j = i; j < pos; j++){

                if( s[j] == '0' ) cnt++;    

                else t = t+s[j];    

            }    

            for(int j = 0; j < cnt; j++ ) t = '0' + t;    

            t = s[pos] + t;

            for(int j = pos+1; j < len; j++ ) 

                t = t + s[j];

        }    

        //printf("%s\n", t.c_str() );

}



int main(){

    int T;

    scanf("%d", &T);

    while( T-- ){

        scanf("%s", s);

        t.clear();

        len = strlen(s);

        int i = 1; t = s[0];

        if( s[0] == '0' ) gao(1);    

        else{

            while( (i<len) && (s[i]!='0') ){

                if( s[i] > t[0] ) t = t+s[i];

                else t = s[i] + t;

                i++;    

            }    

            if( i < len ) gao(i);    

        }

        printf("%s\n", t.c_str() );    

    }

    return 0;

}
View Code

  精简的代码思路:  就是找一个非0最小所在下标pos, 放在最前面. 其中 下标i < pos的, 用大在后,小在前.  然后i > pos的直接原样丢后面...不用考虑0的特殊情况....真心好..

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<string>

#include<algorithm>

using namespace std;



const int N = 110;



char s[N];



int main(){

    int _;

    scanf("%d", &_);

    while( _-- ){

        scanf("%s", s);

        string t;

        t += s[0];

        char ch = '9';

        int pos;

        for(int i = 0; s[i]; i++)

            if( (s[i]!='0') && (ch>=s[i]) ) ch = s[pos=i];

        for(int i = 1; s[i]; i++){

            if( i == pos ) t = s[i] + t;

            else if( i < pos ){

                if( s[i] <= t[0] ) t = s[i] + t;

                else t = t + s[i];

            }

            else t = t + s[i];    

        }

        printf("%s\n", t.c_str() );    

    }

    return 0;

}
View Code

 

你可能感兴趣的:(总结)