SRM 500(2-1000pt)
DIV2 1000pt
题意:给定两个集合A和B,A = {b1*q1i | 0 <= i <= n1-1},B = {b2*q2i | 0 <= i <= n2-1},问将AB两个集合合并之后的集合中元素的个数。(注意,每个集合中每个元素只能有一个)。其中0 <= b1,b2,q1,q2 <= 5*10^8,1 <= n1,n2 <= 10^5。
解法:首先,我们称b = 0或者q = 0或者q = 1的集合为特殊集合,因为特殊集合中最多有两个元素。若至少有一个集合为特殊集合,则此问题容易解决。下面考虑两个集合都不为特殊集合的情况。
其实,如果不是A和B中的数太大,我们可以将他们每个都求出来,然后放到一个set<long long>里面,返回set.size()即可,时间复杂度O(n1 + n2)。我们需要找到一种表示这些大数的方法。考虑整数的唯一分解式。
每个整数可以表示成(a1^p1) * (a2^p2) * (a3^p3) *..* (ak^pk)的形式,也就是说,我们只需要统一所有会用到的质数,然后把p1,p2..pk放到一个vector里面,就可以表示每个整数。然后用一个set<vector<long long> >即可统计元素的个数。
tag: math, set
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // BEGIN CUT HERE 2 /* 3 * Author: plum rain 4 * score : 5 */ 6 /* 7 8 */ 9 // END CUT HERE 10 #line 11 "GeometricProgressions.cpp" 11 #include <sstream> 12 #include <stdexcept> 13 #include <functional> 14 #include <iomanip> 15 #include <numeric> 16 #include <fstream> 17 #include <cctype> 18 #include <iostream> 19 #include <cstdio> 20 #include <vector> 21 #include <cstring> 22 #include <cmath> 23 #include <algorithm> 24 #include <cstdlib> 25 #include <set> 26 #include <queue> 27 #include <bitset> 28 #include <list> 29 #include <string> 30 #include <utility> 31 #include <map> 32 #include <ctime> 33 #include <stack> 34 35 using namespace std; 36 37 #define CLR(x) memset(x, 0, sizeof(x)) 38 #define PB push_back 39 #define SZ(v) ((int)(v).size()) 40 #define zero(x) (((x)>0?(x):-(x))<eps) 41 #define out(x) cout<<#x<<":"<<(x)<<endl 42 #define tst(a) cout<<#a<<endl 43 #define CINBEQUICKER std::ios::sync_with_stdio(false) 44 45 typedef vector<int> VI; 46 typedef vector<string> VS; 47 typedef vector<double> VD; 48 typedef long long int64; 49 50 const double eps = 1e-8; 51 const double PI = atan(1.0)*4; 52 const int maxint = 2139062143; 53 const int N = 10005; 54 const int M = 10005; 55 56 int an[4][N]; 57 int tmp_sz; 58 int64 bn[4][N]; 59 60 int inte_dev(int x, int* an, int64* bn) 61 { 62 int all = -1; 63 for (int i = 2; i*i <= x;){ 64 if (!(x%i)){ 65 an[++all] = i; 66 bn[all] = 0; 67 } 68 while (!(x%i)){ 69 ++ bn[all]; 70 x /= i; 71 } 72 if (i == 2) ++ i; 73 else i += 2; 74 } 75 ++ all; 76 if (x != 1){ 77 an[all] = x; 78 bn[all++] = 1; 79 } 80 return all; 81 } 82 83 int gao(int64 x, int a) 84 { 85 int ret = 0; 86 while (!(x % a)){ 87 x /= a; 88 ++ ret; 89 } 90 return ret; 91 } 92 93 VI vadd(VI a, VI b) 94 { 95 VI ret; ret.clear(); 96 for (int i = 0; i < tmp_sz; ++ i) 97 ret.PB (a[i]+b[i]); 98 return ret; 99 } 100 101 class GeometricProgressions 102 { 103 public: 104 int count(int aa, int b, int n, int c, int d, int m){ 105 int64 a[4]; 106 a[0] = aa; a[1] = b; a[2] = c; a[3] = d; 107 if (!a[2] || !a[3] || a[3] == 1){ 108 swap (a[0], a[2]); swap (a[1], a[3]); swap (n, m); 109 } 110 if (!a[0] || !a[1] || a[1] == 1){ 111 set<int64> tmp; 112 tmp.insert(a[0]); 113 if (n > 1) tmp.insert(a[1]*a[0]); 114 115 int cnt = 0, sz_tmp = tmp.size(); 116 int64 now = a[2]; 117 for (int i = 0; i < m; ++ i){ 118 if (tmp.count(now)) ++ cnt; 119 else tmp.insert(now); 120 now *= a[3]; 121 if (now > 25e16) 122 return m + sz_tmp - cnt; 123 } 124 return tmp.size(); 125 } 126 127 int64 all[4]; 128 for (int i = 0; i < 4; ++ i) 129 all[i] = inte_dev(a[i], an[i], bn[i]); 130 131 set<int> tmp; 132 VI tt; tt.clear(); 133 for (int i = 0; i < 4; ++ i) 134 for (int j = 0; j < all[i]; ++ j) 135 if (!tmp.count(an[i][j])){ 136 tmp.insert (an[i][j]); 137 tt.PB (an[i][j]); 138 } 139 140 vector<int> v[4]; 141 for (int i = 0; i < 4; ++ i) 142 v[i].clear(); 143 tmp_sz = tmp.size(); 144 for (int i = 0; i < 4; ++ i) 145 for (int j = 0; j < tmp_sz; ++ j) 146 v[i].PB (gao(a[i], tt[j])); 147 148 set<VI > ans; 149 ans.erase(ans.begin(), ans.end()); 150 VI now = v[0]; 151 for (int i = 0; i < n; ++ i){ 152 if (!ans.count(now)) ans.insert(now); 153 now = vadd(now, v[1]); 154 } 155 now = v[2]; 156 for (int i = 0; i < m; ++ i){ 157 if (!ans.count(now)) ans.insert(now); 158 now = vadd(now, v[3]); 159 } 160 return ans.size(); 161 } 162 163 // BEGIN CUT HERE 164 public: 165 //void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); } 166 void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0();} 167 private: 168 template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); } 169 void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } } 170 void test_case_0() { int Arg0 = 7; int Arg1 = 4; int Arg2 = 5; int Arg3 = 8; int Arg4 = 0; int Arg5 = 1; int Arg6 = 6; verify_case(0, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); } 171 void test_case_1() { int Arg0 = 3; int Arg1 = 2; int Arg2 = 5; int Arg3 = 2; int Arg4 = 3; int Arg5 = 5; int Arg6 = 9; verify_case(1, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); } 172 void test_case_2() { int Arg0 = 1; int Arg1 = 1; int Arg2 = 1; int Arg3 = 0; int Arg4 = 0; int Arg5 = 1; int Arg6 = 2; verify_case(2, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); } 173 void test_case_3() { int Arg0 = 3; int Arg1 = 4; int Arg2 = 100500; int Arg3 = 48; int Arg4 = 1024; int Arg5 = 1000; int Arg6 = 100500; verify_case(3, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); } 174 175 // END CUT HERE 176 177 }; 178 179 // BEGIN CUT HERE 180 int main() 181 { 182 // freopen( "a.out" , "w" , stdout ); 183 GeometricProgressions ___test; 184 ___test.run_test(-1); 185 return 0; 186 } 187 // END CUT HERE
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。