2019 HDOJ Multi-University Training Contest Stage 4(杭电多校)

Posted jhseng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 HDOJ Multi-University Training Contest Stage 4(杭电多校)相关的知识,希望对你有一定的参考价值。

很抱歉过了这么多天才补这场,最近真的挺忙的……

出题人是朝鲜的(目测是金策工业?),挺难。

题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=851


A:

签到题。

对于当前的点,若其编号为偶数,则可与1相连使得边权贡献为0。否则从低位向高位找当前点编号的二进制表示的第一个0,使这个0变为1,其他位置变为0并检查新的数字是否小于等于n。若小于等于n则贡献为0,反之贡献为1。

技术图片
 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 /* namespace */
17 using namespace std;
18 /* header end */
19 
20 const int maxn = 2e7;
21 ll bin[60];
22 int ans[maxn];
23 
24 int main() 
25     bin[0] = 1;
26     for (int i = 1; i <= 40; i++) bin[i] = (bin[i - 1] << 1);
27     int T; cin >> T;
28     while (T--) 
29         int n;
30         cin >> n;
31         int sum = 0;
32         for (int i = 1; i <= n; i++) 
33             if (!(i & 1)) 
34                 ans[i] = 1;
35                 continue;
36             
37             for (int j = 0; j <= 31; j++) 
38                 if ((i & bin[j]) == 0) 
39                     if (bin[j] <= n) ans[i] = bin[j];
40                     else 
41                         ans[i] = 1;
42                         sum++;
43                     
44                     break;
45                 
46             
47         
48         cout << sum << endl;
49         for (int i = 2; i <= n - 1; i++) cout << ans[i] << " ";
50         cout << ans[n] << endl;
51     
52     return 0;
53 
View Code

B:

C:

D:

E:

F:

G:

一开始还以为是反向bfs,白给了两发。

题目说明120步之后就能作判断。可以先比较初始矩阵和目标矩阵数字1、2、3、4的位置,再比较5、6、7、8,以此类推。因为前面的数排完之后就没有后效性了。可以从1*n的矩阵思考,再数学归纳到n*n来思考这个问题。

事实上这是个关于奇数码游戏(就是题目给的游戏)的结论题:奇数码游戏两个局面可达,当且仅当两个局面下网格中的数依次写成一行含有n^2-1个元素的序列中,逆序对个数的奇偶性相同。该结论必要性显然:当空格左右移动时,写成的序列显然不变,不改变逆序对个数奇偶性;空格上下移动时,相当于某个数与它前(或后)边的n-1个数交换了位置,因为n-1是购书,所以逆序对数的变化也只能是偶数。

技术图片
 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 /* namespace */
17 using namespace std;
18 /* header end */
19 
20 const int maxn = 20;
21 
22 int main() 
23     int t; scanf("%d", &t);
24     while (t--) 
25         int ans = 0, a[maxn];
26         rep0(i, 0, 16) 
27             scanf("%d", &a[i]);
28             if (!a[i]) ans += i / 4 + 1 + i % 4 + 1, a[i] = 16;
29             rep1(j, 0, i) if (a[j] > a[i]) ans++;
30         
31         if (ans & 1) puts("No");
32         else puts("Yes");
33     
34     return 0;
35 
View Code

H:

给定一维坐标系上的n个整点和m次询问,每次询问给定L,R,p,K。问在区间[L,R]内到点p距离第K小,输出其距离。

二分答案,看区间[p-ans,p+ans]内有没有k个数。

技术图片
 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 /* namespace */
17 using namespace std;
18 /* header end */
19 
20 const int maxn = 1e6 + 10;
21 int a[maxn], root[maxn], cnt = 0;
22 
23 struct Node 
24     int l, r, sum;
25  segt[maxn * 40];
26 
27 void update(int pos, int curl, int curr, int &curroot, int &lastroot) 
28     segt[++cnt] = segt[lastroot], segt[cnt].sum++, curroot = cnt;
29     if (curl == curr) return;
30     int mid = curl + curr >> 1;
31     if (pos <= mid) update(pos, curl, mid, segt[curroot].l, segt[lastroot].l);
32     else update(pos, mid + 1, curr, segt[curroot].r, segt[lastroot].r);
33 
34 
35 int query(int lRoot, int rRoot, int curl, int curr, int ql, int qr) 
36     if (ql <= curl && curr <= qr)
37         return segt[rRoot].sum - segt[lRoot].sum;
38     if (curl == curr) return 0;
39     int mid = curl + curr >> 1;
40     if (qr <= mid) return query(segt[lRoot].l, segt[rRoot].l, curl, mid, ql, qr);
41     else if (ql > mid) return query(segt[lRoot].r, segt[rRoot].r, mid + 1, curr, ql, qr);
42     else return query(segt[lRoot].l, segt[rRoot].l, curl, mid, ql, mid) + query(segt[lRoot].r, segt[rRoot].r, mid + 1, curr, mid + 1, qr);
43 
44 
45 int main() 
46     int t; scanf("%d", &t);
47     while (t--) 
48         cnt = 0;
49         int n, q, maxx; scanf("%d%d", &n, &q);
50         for (int i = 1; i <= n; i++) 
51             scanf("%d", &a[i]);
52             maxx = max(maxx, a[i]);
53         
54         for (int i = 1; i <= n; i++)
55             update(a[i], 1, maxx, root[i], root[i - 1]);
56         int lastAns = 0;
57         while (q--) 
58             int l, r, p, k; scanf("%d%d%d%d", &l, &r, &p, &k);
59             l ^= lastAns, r ^= lastAns, p ^= lastAns, k ^= lastAns;
60             int upBound = maxx, lowBound = 0, ans = maxx;
61             while (lowBound <= upBound) 
62                 int mid = lowBound + upBound >> 1;
63                 if (query(root[l - 1], root[r], 1, maxx, p - mid, p + mid) >= k) 
64                     ans = mid;
65                     upBound = mid - 1;
66                  else lowBound = mid + 1;
67             
68             lastAns = ans;
69             printf("%d\n", ans);
70         
71     
72     return 0;
73 
View Code

J:

给定正整数n(n>=2),把n唯一分解之后输出最小的幂次。

把n用4000以内的质数分解,然后判断剩下的是否为p2,p3,p4,p2q2的形式即可,若都不是,答案为1。

技术图片
 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* define */
 4 #define ll long long
 5 #define dou double
 6 #define pb emplace_back
 7 #define mp make_pair
 8 #define sot(a,b) sort(a+1,a+1+b)
 9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
10 #define rep0(i,a,b) for(int i=a;i<b;++i)
11 #define eps 1e-8
12 #define int_inf 0x3f3f3f3f
13 #define ll_inf 0x7f7f7f7f7f7f7f7f
14 #define lson (curpos<<1)
15 #define rson (curpos<<1|1)
16 /* namespace */
17 using namespace std;
18 /* header end */
19 
20 const int maxn = 4010;
21 int t, tot, p[maxn], vis[maxn];
22 ll n;
23 
24 void getPrime() 
25     for (int i = 2; i < maxn; i++) 
26         if (!vis[i]) p[tot++] = i;
27         for (int j = 0; j < tot && i * p[j] < maxn; j++) 
28             vis[i * p[j]] = 1;
29             if (i % p[j] == 0) break;
30         
31     
32 
33 
34 int main() 
35     getPrime();
36     int t; scanf("%d", &t);
37     while (t--) 
38         scanf("%lld", &n);
39         int cnt = int_inf, flag = 0;
40         for (int i = 0; i < tot; i++)
41             if (n % p[i] == 0) 
42                 int num = 0;
43                 while (n % p[i] == 0) 
44                     num++; n /= p[i];
45                 
46                 if (num == 1) flag = 1;
47                 cnt = min(cnt, num);
48             
49         if (flag) 
50             puts("1");
51             continue;
52         
53         if (n == 1) 
54             printf("%d\n", cnt);
55             continue;
56         
57         ll tmp = pow(n, 0.25);
58         if (tmp * tmp * tmp * tmp == n) cnt = min(cnt, 4);
59         else 
60             ++tmp;
61             if (tmp * tmp * tmp * tmp == n) cnt = min(cnt, 4);
62             else 
63                 tmp = pow(n, 0.5);
64                 if (tmp * tmp == n) cnt = min(cnt, 2);
65                 else 
66                     tmp++;
67                     if (tmp * tmp == n) cnt = min(cnt, 2);
68                     else 
69                         tmp = pow(n, 1.0 / 3);
70                         if (tmp * tmp * tmp == n) cnt = min(3, cnt);
71                         else 
72                             tmp++;
73                             if (tmp * tmp * tmp == n) cnt = min(3, cnt);
74                             else cnt = min(1, cnt);
75                         
76                     
77                 
78             
79         
80         printf("%d\n", cnt);
81     
82     return 0;
83 
View Code

 

以上是关于2019 HDOJ Multi-University Training Contest Stage 4(杭电多校)的主要内容,如果未能解决你的问题,请参考以下文章

2019 HDOJ Multi-University Training Contest Stage 10(杭电多校)

2019 HDOJ Multi-University Training Contest Stage 2(杭电多校)

2019 HDOJ Multi-University Training Contest Stage 4(杭电多校)

HDOJ/HDU 1256 ???8(????????????~??????)

HDOJ-2037

HDOJ-2048