2017多校Round7(hdu6120~hdu6132)

补题进度:9/13

1001

  待填坑

1002(数学推导)

题意

  有一个按顺序的n个点的k叉树,问每个点子树个数的异或和是多少(n,k<=1e18)

分析

  可以先求出最大的d,满足d以上都是满K叉树,最后一层是一些零散的点

  然后枚举每一层,每一层的点分为三种,一种是最下面的孩子深度是d+1,一种是部分孩子的深度是d+1,一种是最下面孩子深度都是d,分别统计答案

  注意特判k=1的时候,这个时候等价于求1^2^3^4^5^6....^n的值

  我们可以把四个四个放在一组,如果k是一个偶数,那么k^(k+1)=1,(k+2)^(k+3)=1,所以k^(k+1)^(k+2)^(k+3)=1^1=0

  所以1异或到n的值是和n%4的值有关

1003(神奇套路)

题意

  有一个n行m列的棋盘,最初每个位置是指定的红色或蓝色或白色。你要将白色的位置染成红色或蓝色,使得对于任意一个长宽均为偶数的连续子棋盘,其中红色和蓝色的位置数相等。(1<=m,n<=1000)

分析

  题解给出了很神奇的套路

  首先“任意一个长宽均为偶数的连续子棋盘”,我们只需要考虑边长为2的小棋盘,边长为4、6、8的这些都是若干个2*2的拼起来的

  我们设红色是0,蓝色是1,对于棋盘上的(x,y),如果x+y是奇数并且该位置不是?,那么就把这一位置颜色反转

  我们发现原来任意一个2*2的子棋盘合法等价于现在新的任意一个2*2的子棋盘对角线上的和相同

  进一步发现这等价于:要么新棋盘的每一行上的数都各自相同,要么新棋盘的每一列上的数都各自相同

  于是就可以计算答案了

  具体实现的时候,我们可以记录每一行、每一列的颜色占用情况,如果发现同一行出现了两种固定颜色,那么说明每一行颜色各自相同这个是不可能的了;列的情况也是同理

  最后计算结果就是2^自由行个数 + 2^自由列个数,但是要除去一些重复情况,如果固定颜色中只出现了一种,那么最终答案需要减去一;如果固定颜色两种都没出现,那么答案要减去二

1004

  待填坑

1005(数学题)

题意

  给定正整数a,求对于所有正整数b,a mod b有多少种可能的结果。1<=a<=1e9

分析

  显然小于a/2的所有数c都可以作为结果,只需要取b=a-c,另外a本身也可以

  所以答案就是(a-1)/2+2

1006(状压DP)

题意

  求从不大于n的所有正整数中选出至少1个且至多k个使得乘积不包含平方因子的方案数(1<=n,k<=500)

分析

  此套路出自于NOI2015寿司晚宴

  我们可以把它看做一个背包问题,我们将500以内所有质因数都压缩成二进制位,然后就相当于有500个物品,取或者不取,取了的话要保证质因数集合每个位不能超过1

  但是问题是500以内的素数有90多个,无法压缩成二进制位

  我们可以将sqrt(500)以内的素数压缩成二进制位(8个),为什么这样呢?因为1~500里的所有数字,其大于sqrt(500)的质因数顶多只有一个

  于是对于1~500以内所有素数我们都可以把它看做一个包,对于1~500内的所有无平方因子数x,我们都可以求出其最大质因数y,把x对于前8个素数的分解情况丢入背包y种,把这个作为背包y中的一个物品

  特别的,如果2*3*5这种全部是由前8个素数乘积构成的数,那就丢到其本身的那个背包

  现在问题就相当于是有若干个背包,每个背包里的物品我只能选一个(因为如果多选会造成该较大质因子重复),然后求前八个素数分解情况不冲突的方案数

  很经典的分组背包了,dp[i][s][k]表示前i个包,目前前8个素数选择情况为s,选了k个数的方案数

  第一维滚动掉即可

1007(网络流)

题意

  有n个小朋友,标号为1到n,你要给每个小朋友至少1个且至多m个的糖果。小朋友们共提出k个要求,每个要求包括三个整数x,y,z表示x号小朋友得到的糖果数减去y号小朋友得到的糖果数,结果应当不大于z。如果你给i号小朋友j颗糖果,他会获得w(i,j)的满意度,你需要最大化所有小朋友的满意度和。1<=n,m<=50,1<=k<=150,1<=w(i,j)<=1000

分析

  来自题解的建图方法。

  容易想到拆点,用i.j这点表示给第i个孩子至少j块糖,当这个点属于S集合时所代表条件成立。然后i.j->i.j+1连1000-wi,j,i.m向T连1000-wi,m,S向i.1连inf。如果存在ax-ay>=z,x.k->y.k+z连inf。跑最小割,再用n*1000减掉答案。

1008(计算几何)

题意

  平面直角坐标系上有n个整点,第i个点有一个点权val[i],坐标是(xi,yi),?其中不存在任意两点连成的直线经过原点。这些整点两两之间连有一条线段,线段的权值为其两端点的权值之积。你需要作一条过原点而不过任意一个给定整点的直线,使得和这条直线相交的线段的权值和最大。1<=n<=5e4,1<=val<=10^4,|xi|,|yi|<=1e9

分析

  很容易想到极角排序,答案的统计就是直线两边点集权值和的乘积,所以O(n)扫一圈就可以了

  注意的一点是直线从-π到π的过程中,直线的另一边可能从第二象限跳到第三象限,所以提前将前n个点接到第n个点后面,极角+2π

1009(二次剩余)

  队友补了,不管了

1010(找规律)

题意

  有一个长度为n的整数序列an,对其做m次前缀异或和,求最终的序列(1<=n<=2e5,1<=m<=1e9)

分析

  dp[i][j]=dp[i-1][j]^dp[i][j-1]=dp[i-2][j]^dp[i-1][j-1]^dp[i-1][j-1]^dp[i][j-2]=dp[i-2][j]^dp[i][j-2]

  进一步归纳可以得到dp[i][j]=dp[i-2^k][j]^dp[i][j-2^k]

  这只需要从1~m倍增就行了

  时间复杂度O(nlogm)

1011(模拟)

  略,根据题意的构造方式模拟即可

1012

  待填坑

1013

  待填坑

时间: 2024-10-06 22:53:14

2017多校Round7(hdu6120~hdu6132)的相关文章

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