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 }