hdu 4610 Cards

解法:

  假设n分解因式之后的形式是n = a1 ^ b1 * a2 ^ b2 *...*an ^ bn

  它的因子个数就是(b1+1)*(b2+1)*...*(bn+1)

  因子和是(1+a1 ^ 1+..+a1 ^ b1)*(1 + a2 ^ 1 +..+a2 ^ b2 )*..*(1 + an ^ 1 + ... +an ^bn)

  所以因子个数为素数的条件就是只有一个素因子并且b1 + 1为素数;

    因子和为素数的条件就是只有一个素因子并且(1 + a1 ^ 1+..+a 1 ^ b1)为素数

  接下来要判断因子积是不是完全平方数,因为因子都是成对出现的 i * n / i == n。。。只有完全平方数有个例外。。然后根据这个判断就行。

 

  按照数满足的条件可以分为16种,然后暴力枚举取哪些就行了,要注意的是对于每一种一定要取一个。。。

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<bitset>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<vector>
  7 #include<algorithm>
  8 using namespace std;
  9 typedef long long ll;
 10 const int N = (int)4e6+10;
 11 const int M = (int)1e6+10;
 12 typedef pair<int,int> pii;
 13 bool p[N];
 14 int prime[M];
 15 void init(){
 16     memset(p,true,sizeof(p));
 17     p[0] = p[1] = false;
 18     for(int i=2;i*i<N;i++)
 19         for(int j=i;j*i<N;j++)
 20             p[i*j] = 0;
 21     prime[0] = 0;
 22     for(int i=2;i<N;i++)
 23         if(p[i])prime[++prime[0]] = i;
 24 }
 25 vector<pii>factor;
 26 void div(int n){
 27     factor.clear();
 28     for(int i=1;prime[i] * prime[i] <= n;i++){
 29         if(n % prime[i]  == 0){
 30             int cnt = 0;
 31             while(n % prime[i] == 0){
 32                 n /= prime[i];
 33                 ++cnt;
 34             }
 35             factor.push_back(make_pair(prime[i],cnt));
 36         }
 37     }
 38     if(n > 1)factor.push_back(make_pair(n,1));
 39 }
 40 ll Pow(ll a,ll b){
 41     ll ans = 1;
 42     while(b){
 43         if(b&1)ans = ans * a;
 44         a = a * a;
 45         b >>= 1;
 46     }
 47     return ans;
 48 }
 49 bool isPrime_amount(int n){
 50     if(factor.size() > 1|| n==1 )return false;
 51     return p[factor[0].second + 1];
 52 }
 53 bool isPrime_sum(int n){
 54     if(factor.size() > 1|| n== 1)return false;
 55     int a = factor[0].first,b = factor[0].second;
 56     int sum = 1LL*(Pow(a,b+1) - 1) / (a - 1);
 57     return p[sum];
 58 }
 59 bool isSquare(ll n){
 60     ll _ = sqrt(n*1.0);
 61     return _ * _ == n;
 62 }
 63 bool isSquare_product(int n){
 64     int all = 1;
 65     for(int i=0;i<factor.size();i++)
 66         all *= factor[i].second + 1;
 67     ll sq = sqrt(n*1.0);
 68     ll cur = 1;
 69     int p = all >> 1;
 70     if(p & 1)cur *= n;
 71     if(all & 1)cur *= sq;
 72     return isSquare(cur);
 73 }
 74 
 75 int extra[5];
 76 int V[16],cur[5],hash[16];
 77 int have[16];
 78 int main(){
 79     for(int i=0;i<16;i++){
 80         int all = 0;
 81         for(int j=0;j<4;j++)
 82             if(!(i&(1<<j)))++all;
 83         have[i] = all;
 84     }
 85     init();
 86     int T,n,K;
 87     scanf("%d",&T);
 88     while(T--){
 89         memset(V,0,sizeof(V));
 90         scanf("%d%d",&n,&K);
 91         for(int i=1;i<=n;i++){
 92             int a,b;
 93             scanf("%d%d",&a,&b);
 94             int flag = 15,cnt = 0;
 95             div(a);
 96             if(p[a])flag ^= 1<<0 ,cnt ++;//puts("1 ok");
 97             if(isPrime_amount(a)) flag ^= 1<<1,cnt ++;//puts("2 ok");
 98             if(isPrime_sum(a))flag ^= 1<<2,cnt ++;//puts("3 ok");
 99             if(isSquare_product(a)) flag ^= 1<<3,cnt++;//puts("4 ok");
100             V[flag] += b;
101             if(i!=1)printf(" ");
102             printf("%d",cnt);
103         }
104         puts("");
105         int ans = -(~0u>>2);
106         
107         for(int i=0;i< 4;i++)scanf("%d",&extra[i]);
108         for(int i=0;i < 1<<16;i++){
109             memset(cur,0,sizeof(cur));
110             int res = K,number = 0,all = 0;
111             int flag = 15;
112             for(int j = 0;j < 16;j++){
113                 if(i&(1<<j)){
114                     if(V[j] > 0){
115                         flag &= j;
116                         res --;
117                         all += have[j];
118                         cur[have[j]] += V[j] - 1;
119                     }else{
120                         res = -1;
121                         break;
122                     }
123                 }
124             }
125             if(res < 0 )continue;
126             for(int k=4;k >= 0 && res > 0;k--){
127                 if(cur[k] <= res){
128                     all += k * cur[k];
129                     res -= cur[k];
130                 }else{
131                     all += res * k;
132                     res =0;
133                 }
134             }
135             if(res == 0){
136                 for(int j=0;j<4;j++)
137                     if(flag & (1<<j))all += extra[j];
138                 ans = max(ans,all);
139             }
140         }
141 
142         printf("%d\n",ans);
143     }
144     return 0;
145 }

 

 

posted @ 2013-07-31 11:10  silver__bullet  阅读(402)  评论(0编辑  收藏  举报