hdu 4610 Cards (分解质因数)

来源:互联网 发布:3d artist软件 编辑:程序博客网 时间:2024/06/10 16:32

数学推导,快速求素数,模拟

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;const int MAXN = 4000010;/**    n = a0^b0 * a1*b1 * a2^b2 * a3^b3 ......    a均为素数    因子数量 = (b0+1)*(b1+1)*(b2+1).....    因子数量为素数:仅有一个素因子且(b0+1)为素数    因子和 = (1 + a0^1 + a0^2 + ... a0^b0)* (1 + a1^1 + a1^2 + ... a1^b1)    因子和为素数:仅有一个素因子且(1 + a0^1 + a0^2 + ... a0^b0)为素数    因子的乘积为 n^x * (n为平方数?n^0.5 : 1)*/int isPrim[MAXN];int prime[MAXN >> 2];void getPrime(){    memset ( isPrim, 1, sizeof isPrim );    isPrim[0] = isPrim[1] = 0;    for ( int i = 2; i <= MAXN; ++i )    {        if ( isPrim[i] ) { prime[++prime[0]] = i; }        for ( int j = 1; j <= prime[0] && prime[j]*i <= MAXN; ++j )        {            isPrim[prime[j]*i] = 0;            if ( i % prime[j] == 0 )            {                break;            }        }    }}ll fc[2][200];/// 分解质因数int getFactor ( int x ){    ll tmp = x;    int fnum = 0;    for ( int i = 1; prime[i]*prime[i] <= tmp; ++i )    {        fc[1][fnum] = 0;        if ( tmp % prime[i] == 0 )        {            fc[0][fnum] = prime[i];            while ( tmp % prime[i] == 0 )            {                fc[1][fnum]++;                tmp /= prime[i];            }            fnum++;        }    }    if ( tmp > 1 )    {        fc[0][fnum] = tmp, fc[1][fnum++] = 1;    }    return fnum;}const int MAXM = 1010;struct node{    int a, b;} c[MAXM];int d[5], v[16], rest[16];ll mPow ( ll a, int t ){    ll s = 1, tp = a;    while ( t )    {        if ( t & 1 ) { s *= tp; }        tp *= tp;        t >>= 1;    }    return s;}ll getSum ( ll a, ll b ){    return ( mPow ( a, b + 1 ) - 1 ) / ( a - 1 );}int mmp[16];int judge ( int dx ){    int num = c[dx].a;    int sn = 0, cnt = 0;    if ( num == 1 )    {        cnt++;        sn |= 1 << 3;        v[sn] += c[dx].b;        mmp[sn] = 1;        return cnt;    }    int fnum = getFactor ( num );    /// 1    if ( fnum == 1 && fc[1][0] == 1 ) { cnt++, sn |= 1; }    /// 2    if ( fnum == 1 && isPrim[1 + fc[1][0]] ) { cnt++, sn |= 1 << 1; }    /// 3    if ( fnum == 1 && isPrim[getSum ( fc[0][0], fc[1][0] )] ) { cnt++, sn |= 1 << 2; }    /// 4    int sum = 1, ct = 1, y = 1;    for ( int i = 0; i < fnum; ++i )    {        sum *= fc[1][i] + 1;    }    if ( sum & 1 ) { y = sqrt ( ( double ) num ); }    sum >>= 1;    if ( sum & 1 ) { ct = num; }    ct *= y;    y = sqrt ( ( double ) ct );    if ( y * y == ct )    {        cnt++, sn |= 1 << 3;    }    v[sn] += c[dx].b;    mmp[sn] = cnt;    return cnt;}int rk[16] = {15, 14, 13, 11, 7, 12, 10, 9, 6, 5, 3, 8, 4, 2, 1, 0};int main(){#ifdef  __GNUC__    freopen ( "in.txt", "r", stdin );#endif // __GNUC__    getPrime();    int t, n, k;    int i, j, h;    scanf ( "%d", &t );    while ( t-- )    {        scanf ( "%d%d", &n, &k );        memset ( v, 0, sizeof v );        for ( i = 0; i < n; ++i )        {            scanf ( "%d%d", &c[i].a, &c[i].b );            if ( i ) { printf ( " " ); }            printf ( "%d", judge ( i ) );        }        puts ( "" );        for ( i = 0; i < 4; ++i )        {            scanf ( "%d", &d[i] );        }        int mxnum = 0x80000000;        /// 1标志取用        for ( i = 0; i < ( 1 << 16 ); ++i )        {            /// 每个状态先来一发            int flg = 0, q = k, sum = 0;            memcpy ( rest, v, sizeof v );            for ( j = 0; j < 16; ++j )            {                if ( i & ( 1 << j ) )                {                    if ( rest[j] > 0 )                    {                        flg |= j;                        --q;                        --rest[j];                        sum += mmp[j];                    }                    else                    {                        q = -1;                        break;                    }                }            }            flg = 15 & ( ~flg );            if ( q < 0 ) { continue; }            for ( j = 0; j < 16 && q; ++j )            {                h = rk[j];                if ( i & ( 1 << h ) )                {                    if ( rest[h] <= q )                    {                        sum += mmp[h] * rest[h];                        q -= rest[h];                        rest[h] = 0;                    }                    else                    {                        sum += mmp[h] * q;                        q = 0;                    }                }            }            if ( !q )            {                for ( j = 0; j < 4; ++j )                    if ( ( 1 << j ) & flg ) { sum += d[j]; }                mxnum = max ( mxnum, sum );            }        }        printf ( "%d\n", mxnum );    }    return 0;}


原创粉丝点击