某模拟题题解 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 }

转载于:https://www.cnblogs.com/yyf0309/p/6075201.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值