某模拟题题解 2016.11.17
第一题并不是很难,首先筛出1 ~ sqrt(r)中的所有质数,然后用再用筛法直接筛[l, r]中的质数。筛出来找一遍就行了。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<sstream> 8 #include<algorithm> 9 #include<map> 10 #include<set> 11 #include<queue> 12 #include<vector> 13 #include<stack> 14 using namespace std; 15 typedef bool boolean; 16 #define INF 0xfffffff 17 #define smin(a, b) a = min(a, b) 18 #define smax(a, b) a = max(a, b) 19 template<typename T> 20 inline void readInteger(T& u){ 21 char x; 22 int aFlag = 1; 23 while(!isdigit((x = getchar())) && x != '-'); 24 if(x == '-'){ 25 x = getchar(); 26 aFlag = -1; 27 } 28 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 29 ungetc(x, stdin); 30 u *= aFlag; 31 } 32 33 long long l, r; 34 boolean isPrime[1000001]; 35 vector<int> p; 36 37 inline void init(){ 38 readInteger(l); 39 readInteger(r); 40 } 41 42 inline void getList(){ 43 int limit = (int)sqrt(r + 0.5); 44 for(int i = 2; i <= limit; i++){ 45 if(!isPrime[i]){ 46 p.push_back(i); 47 for(int j = i * i; j <= limit; j += i){ 48 isPrime[j] = true; 49 } 50 } 51 } 52 } 53 54 inline void solve(){ 55 int result = 0; 56 memset(isPrime, 0, sizeof(isPrime)); 57 for(int i = 0; i < (signed)p.size(); i++){ 58 int pri = p[i]; 59 int bot = l / pri; 60 for(int j = bot; j * 1LL * pri <= r; j++){ 61 long long val = j * 1LL * pri; 62 if(val >= l && val != pri){ 63 isPrime[val - l] = true; 64 } 65 } 66 } 67 for(int i = 0; i <= r - l; i++){ 68 if(!isPrime[i] && i + l != 1) result++; 69 } 70 printf("%d", result); 71 } 72 73 int main(){ 74 freopen("prime.in", "r", stdin); 75 freopen("prime.out", "w", stdout); 76 init(); 77 getList(); 78 solve(); 79 return 0; 80 }
这道题就是道计算题(呵呵)。可以直接算出当n = 9, 99, 999...的情况。那么就可以从高位向低位计算。举个例子应该更好说明。
例如n = 1234的时候,首位3,那么1到1000时的各位数字之和为1 * sum3 + (234 + 1) * 1 + 1 * 103,1001到1200的各位数字之和为2 * sum2 + (34 + 1) * 2 + (1 + 2) * 102,大概就是像这样的,继续算下去,然后累加起来就是答案。
关于sum的递推式还是写一下吧sumi = sumi - 1 * 10 + 45 * 10i - 1。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<sstream> 8 #include<algorithm> 9 #include<map> 10 #include<set> 11 #include<queue> 12 #include<vector> 13 #include<stack> 14 using namespace std; 15 typedef bool boolean; 16 #define INF 0xfffffff 17 #define smin(a, b) a = min(a, b) 18 #define smax(a, b) a = max(a, b) 19 template<typename T> 20 inline void readInteger(T& u){ 21 char x; 22 long long aFlag = 1; 23 while(!isdigit((x = getchar())) && x != '-'); 24 if(x == '-'){ 25 x = getchar(); 26 aFlag = -1; 27 } 28 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 29 ungetc(x, stdin); 30 u *= aFlag; 31 } 32 33 template<typename T> 34 inline void putInteger(T u){ 35 if(u == 0){ 36 putchar('0'); 37 return; 38 } 39 if(u < 0){ 40 putchar('-'); 41 u *= -1; 42 } 43 stack<char> s; 44 while(u != 0) s.push(u % 10 + '0'), u /= 10; 45 while(!s.empty()) putchar(s.top()), s.pop(); 46 } 47 48 long long n; 49 long long rn; 50 long long bit; 51 long long power[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; 52 53 inline void init(){ 54 readInteger(n); 55 long long c = n; 56 queue<long long> s; 57 while(c != 0) s.push(c % 10), c /= 10; 58 while(!s.empty()) 59 rn *= 10, rn += s.front(), s.pop(), bit++; 60 } 61 62 long long sum[10]; 63 inline void getList(){ 64 sum[0] = 0; 65 for(long long i = 1; i <= 9; i++) 66 sum[i] = sum[i - 1] * 10 + 45LL * power[i - 1]; 67 } 68 69 inline void solve(){ 70 long long result = 0; 71 while(rn != 0){ 72 long long f = rn % 10; 73 result += f * (n % power[bit - 1] + 1) + f * (f - 1) / 2 * power[bit - 1]; 74 result += f * sum[bit - 1]; 75 rn /= 10, bit--; 76 } 77 putInteger(result); 78 } 79 80 int main(){ 81 freopen("count.in", "r", stdin); 82 freopen("count.out", "w", stdout); 83 init(); 84 getList(); 85 solve(); 86 return 0; 87 }
这题正解线段树 + 扫描线。
首先说说按列处理。车按照横坐标排序,矩形按照纵坐标排序,从1到n开始扫描。
- 当扫描到一个车,加入按照纵坐标建的线段树,直接将对应点的值改为它的横坐标
- 当扫描到某一个矩形的右边那条边,在线段树中查找[y1, y2]的区间最小值,当找到的结果小于x1,则说明存在一行不存在车
然后再按行处理一次,思路几乎是一样的。至于判定, 如果两次扫描都不是完全覆盖, 那么输出NO,否则输出YES
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<sstream> 8 #include<algorithm> 9 #include<map> 10 #include<set> 11 #include<queue> 12 #include<vector> 13 #include<stack> 14 using namespace std; 15 typedef bool boolean; 16 #define INF 0xfffffff 17 #define smin(a, b) a = min(a, b) 18 #define smax(a, b) a = max(a, b) 19 template<typename T> 20 inline void readInteger(T& u){ 21 char x; 22 long long aFlag = 1; 23 while(!isdigit((x = getchar())) && x != '-'); 24 if(x == '-'){ 25 x = getchar(); 26 aFlag = -1; 27 } 28 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 29 ungetc(x, stdin); 30 u *= aFlag; 31 } 32 33 typedef class TreeNode{ 34 public: 35 int from; 36 int end; 37 TreeNode* left; 38 TreeNode* right; 39 int minv; 40 TreeNode(int from, int end):from(from), end(end), left(NULL), right(NULL), minv(-1){ } 41 }TreeNode; 42 43 typedef class SegTree { 44 public: 45 TreeNode* root; 46 SegTree():root(NULL){ } 47 SegTree(int s){ 48 build(root, 1, s); 49 } 50 void pushUp(TreeNode* node){ 51 node->minv = min(node->left->minv, node->right->minv); 52 } 53 void build(TreeNode* &node, int l, int r){ 54 node = new TreeNode(l, r); 55 if(l == r) return; 56 int mid = (l + r) >> 1; 57 build(node->left, l, mid); 58 build(node->right, mid + 1, r); 59 } 60 void update(TreeNode* node, int d, int val){ 61 if(node->from == d && node->end == d){ 62 node->minv = val; 63 return; 64 } 65 int mid = (node->from + node->end) >> 1; 66 if(d <= mid) update(node->left, d, val); 67 else update(node->right, d, val); 68 pushUp(node); 69 } 70 int query(TreeNode* node, int l, int r){ 71 if(node->from == l && node->end == r){ 72 return node->minv; 73 } 74 int mid = (node->from + node->end) >> 1; 75 if(l > mid) return query(node->right, l, r); 76 else if(r <= mid) return query(node->left, l, r); 77 else return min(query(node->left, l, mid), 78 query(node->right, mid + 1, r)); 79 } 80 void clean(TreeNode* node){ 81 if(node == NULL) return; 82 clean(node->left); 83 clean(node->right); 84 delete node; 85 } 86 }SegTree; 87 88 typedef class Point { 89 public: 90 int x; 91 int y; 92 Point(const int x = 0, const int y = 0):x(x), y(y){ } 93 }Point; 94 95 typedef class Rect { 96 public: 97 int x1, x2; 98 int y1, y2; 99 int id; 100 Rect(const int x1 = 0, const int y1 = 0, const int x2 = 0, const int y2 = 0):x1(x1), y1(y1), x2(x2), y2(y2), id(0){} 101 }Rect; 102 103 int n, m, k, q; 104 SegTree lines; 105 SegTree rows; 106 Rect* rs; 107 Point* ps; 108 109 boolean cmpp1(const Point& a, const Point& b){ 110 if(a.x != b.x) return a.x < b.x; 111 return a.y < b.y; 112 } 113 114 boolean cmpp2(const Point& a, const Point& b){ 115 if(a.y != b.y) return a.y < b.y; 116 return a.x < b.x; 117 } 118 119 boolean cmpr1(const Rect& a, const Rect& b){ 120 return a.x2 < b.x2; 121 } 122 123 boolean cmpr2(const Rect& a, const Rect& b){ 124 return a.y2 < b.y2; 125 } 126 127 inline void init(){ 128 readInteger(n); 129 readInteger(m); 130 readInteger(k); 131 readInteger(q); 132 ps = new Point[(const int)(k + 1)]; 133 rs = new Rect[(const int)(q + 1)]; 134 for(int i = 1; i <= k; i++){ 135 readInteger(ps[i].x); 136 readInteger(ps[i].y); 137 } 138 for(int i = 1; i <= q; i++){ 139 readInteger(rs[i].x1); 140 readInteger(rs[i].y1); 141 readInteger(rs[i].x2); 142 readInteger(rs[i].y2); 143 rs[i].id = i; 144 } 145 } 146 147 boolean *isProtected; 148 149 inline void solve_lines(){ 150 isProtected = new boolean[(const int)(q + 1)]; 151 memset(isProtected, true, sizeof(boolean) * (q + 1)); 152 sort(ps + 1, ps + k + 1, cmpp1); 153 sort(rs + 1, rs + q + 1, cmpr1); 154 lines = SegTree(m); 155 int kp = 1, kr = 1; 156 for(int i = 1; i <= n; i++){ 157 while(ps[kp].x == i){ 158 lines.update(lines.root, ps[kp].y, ps[kp].x); 159 kp++; 160 } 161 while(rs[kr].x2 == i){ 162 int fx = lines.query(lines.root, rs[kr].y1, rs[kr].y2); 163 if(fx < rs[kr].x1) isProtected[rs[kr].id] = false; 164 kr++; 165 } 166 } 167 lines.clean(lines.root); 168 } 169 170 inline void solve_rows(){ 171 sort(ps + 1, ps + k + 1, cmpp2); 172 sort(rs + 1, rs + q + 1, cmpr2); 173 rows = SegTree(n); 174 int kp = 1, kr = 1; 175 for(int i = 1; i <= m; i++){ 176 while(ps[kp].y == i){ 177 rows.update(rows.root, ps[kp].x, ps[kp].y); 178 kp++; 179 } 180 while(rs[kr].y2 == i){ 181 if(!isProtected[rs[kr].id]){ 182 int fy = rows.query(rows.root, rs[kr].x1, rs[kr].x2); 183 if(fy >= rs[kr].y1) isProtected[rs[kr].id] = true; 184 } 185 kr++; 186 } 187 } 188 } 189 190 const char str[2][10] = {"NO\n", "YES\n"}; 191 inline void print(){ 192 for(int i = 1; i <= q; i++){ 193 printf("%s", str[isProtected[i]]); 194 } 195 } 196 197 int main(){ 198 freopen("brother.in", "r", stdin); 199 freopen("brother.out", "w", stdout); 200 init(); 201 solve_lines(); 202 solve_rows(); 203 print(); 204 return 0; 205 }