2017多校Round2(hdu6045~hdu6055)

补题进度:10/11

1001(不等式)

根据题意列不等式,解一解就行了

1002(套路)

题意:

给定一个随机产生的1e6*1e6的矩阵和一个1e3*1e3的矩阵,你要回答这个1e3*1e3的小矩阵出现在大矩阵的哪个位置

分析:

每隔1e3行 1e3列去建立一个check矩阵,看看这个check矩阵在不在1e3*1e3的矩阵中(Hash就行)

那么时间复杂度就是O(1e3*1e3*hash)

一个比较好的取法是取一个1*64的矩阵,用unsigned long long把64个压成一位放入hash中

1003(贪心)

样例有误导性,贪心着来就行了,用单调队列维护

1004(找规律+逆序对)

题意:

按照其规则将数字填到一个矩阵中,问能不能通过移动空格使得最后的有序

分析:

若空格左右移动,相当于没有改变排列,逆序对奇偶性不改变

若空格上下移动,那么相当于左右移动了m-1次,因为最后空格又回到了右下角,所以上下移动一定进行偶数次,所以逆序对奇偶性也不该边

我们想要的结果逆序对是偶数,可以猜想如果原序列逆序对个数是偶数那么就可行,否则不可行(官方题解给出了这里的证明)

然后问题就是如何快速求出逆序对了

我们可以按照取数顺序考虑有多少个小于它的数放到了它后面

以第一次(1->p+1->2p+1->...)为例,我们发现对答案的贡献分别是p-1+2*(p-1)+3*(p-1)+..... 这明显可以等差数列求

然后去掉这些之后,我们发现剩余的还是单增的,算法仍旧相同

1005(DP)

题意:

给出一个n的排列(n<=3000),现在可以把连续的一段当作一组,组内进行排序,然后你可以任选两个区间进行交换,问交换后如果能变成12345...n的话,最多能分成多少块

分析:

首先一个n^3的算法很好得到

首先预处理出ma[i][j]和mi[i][j]

我们去枚举需要交换哪两个区间[a,b] [c,d],那么很明显d=ma[a,b],所以只需要去枚举a,b,c,而实际上符合条件的很少,所以这里枚举加些剪枝是可以看作n^2的

很明显我们需要知道f[i][j]表示区间[i,j]变为有序最多能分成多少块

那么求f是n^3的

现在我们要将求f[i][j]变成n^2的

我们发现这个dp中的k取值很有讲究,是决策单调的,并且k不能很大,如果很大就可能导致分割的两个区间不合法

我们用la[i]表示当前以i为左端点的最长可行区间是[i,la[i]],那么f[i][j]=f[i][la[i]]+f[la[i]+1][j]

不过要注意分成的两个区间一定要是左边的左边的最大值小于等于右边的最小值,否则f[i][j]=1

这样我们利用了决策单调性将复杂度降到O(n^2)的了

1006(找规律)

题意:

分析:

刚开始想去找第一层每个数对答案的贡献,但数字量太多了,并没用

可以用特征根求出第一行的通式,然后等比求和求出第一行的S的通式

通过S的通式可以写出第二行的通式,然后再等比求和求出第二行的S的通式

再往下写两行,就能找出Fm,1的规律了

1007(原根)

队友太强辣,把切掉了,我就不补了

1008(单调栈)

题意:

对于一个n*m的方格,每个格子中都包含一种颜色,求出任意一个矩形包含颜色种数的期望。(n,m<=100)

分析:

我们单独去考虑每个位置对答案的贡献

很明显,不同的颜色互不影响,我们可以把相同的颜色挑出来单独计算

容易想到去计算这个东西的反面,当前答案=总的矩阵数-没有被任何一个点覆盖的矩形个数,但这个并不好求,所以这种求反面的想法不可行

我们定义一个位置(i,j)的有效管理矩形是以(i,j)为最左上角的矩形,那么答案就是所有位置的有效管理矩形数的和

那么我们对每一个位置去求有效管理矩形数

1009(莫比乌斯反演)

题意:

n,Ai<=10^5

分析:

对于一个B,我们去求所有数的gcd,如果这个gcd>=2,那么B是合法的,如果这个gcd=1,那么B是不合法的

gcd=1的B数量 + gcd=2的B的数量 + gcd=3的B的数量 + ...  + gcd=min(Ai)的B的数量  ==== 所有B的总数(πAi)

那么我们要求的答案就是πAi - gcd=1的B数量

那么莫比乌斯反演一下ans=Σμ(d)*sum(d)

sum(d)表示公约数为d的时候方案数,很明显sum(d)=π(Ai/d)

这里也要优化,将Ai/d相同的放在一块,这里可以用一个桶来存

1010

待填坑

1011(Trick)

题目:

给了n个整点(n<=500),问有多少个正多边形

分析:

找找规律会发现,只有正方形是可行的

所以可以枚举两个点作为正方形的相邻点,根据两个点去旋转90°以及去做一个平移操作可以得到另外两个点,判断那两个整点是否被读入覆盖就行了

时间复杂度O(n^2)

时间: 2024-08-10 21:29:24

2017多校Round2(hdu6045~hdu6055)的相关文章

hdu6069[素数筛法] 2017多校3

/*hdu6069[素数筛法] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; LL l, r, k; const LL MOD = 998244353LL; int T, n, prime[1100000], primesize; bool isprime[11000000]; void getlist(int listsize) { memset(isprime, 1, sizeof

hdu6035[dfs+思维] 2017多校1

/*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; const double eps=1e-8; const int inf=0x3f3f3f3f; typedef long long LL; vector<int>G[200005]; LL sum[200005]; int c[200005],son[200005],mark[200005]; int n,u,

hdu6034[模拟] 2017多校1

/*hdu6034[模拟] 2017多校1*/ //暴力模拟26个26进制数即可, 要注意进位 #include<bits/stdc++.h> using namespace std; typedef long long LL; const double eps=1e-8; const int inf=0x3f3f3f3f; struct node{ char num[100005]; int ch,high; }bits[30]; const int mod=1000000007; int

hdu6078[优化递推过程] 2017多校4

/*hdu6078[优化递推过程] 2017多校4*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; const LL MOD = 998244353LL; int T, m, n, a[2005], b[2005]; LL sum[2005][3], dp[2005][3]; void solve() { LL ans = 0; for (int i = 1; i <= n; i++) { LL

hdu6074[并查集+LCA+思维] 2017多校4

看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块中的点数. 下面是过程分析.过程中一共运用了两个并查集. [数据]110 31 21 32 42 53 63 74 85 95 109 6 3 1 501 4 2 5 209 10 8 10 40[分析]首先我们将图构建出来我们将m次询问按权值从小到大排序后: 1 4 2 5 209 10 8 10

【链表】2017多校训练3 HDU 6058 Kanade&#39;s sum

acm.hdu.edu.cn/showproblem.php?pid=6058 [题意] 给定一个排列,计算 [思路] 计算排列A中每个数的贡献,即对于每个ai,计算有ni个区间满足ai是区间中的第k大,那么ai对答案的贡献就是ai*ni 以ai为起点,统计ai右边离ai最近的,比ai大的k个数的位置 同理统计左边的位置,组合得到答案 关键是得到比ai大的离ai最近的k个数的位置 因为是排列,所以每个数都不相等,可以记录每个数的位置,然后从小到大枚举ai,这样维护一个双向链表,保证链表中的数就是

hdu6103[尺取法] 2017多校6

/*hdu6103[尺取法] 2017多校6*/ #include <bits/stdc++.h> using namespace std; int T, m; char str[20005]; void solve() { int ans = 0; int n = strlen(str); for (int i = 0; i < n; i++) { int l = 0, r = 0, p1 = i, p2 = i + 1, cost = 0; while (p1 - r >= 0

hdu6098[RMQ+筛法] 2017多校6

/*hdu6098[RMQ+筛法] 2017多校6*/ #include <bits/stdc++.h> using namespace std; int T, n, st[100005][20], len[100005], a[100005]; void st_init() { len[0] = -1; for (int i = 1; i <= n; i++) { st[i][0] = a[i]; len[i] = (i & (i - 1)) == 0 ? len[i - 1]

2017 多校训练 1006 Function

Function Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 273    Accepted Submission(s): 99 Problem Description You are given a permutation a from 0 to n−1 and a permutation b from 0 to m−1. De