其他分享
首页 > 其他分享> > 10月清北学堂培训 Day 5

10月清北学堂培训 Day 5

作者:互联网

今天是廖俊豪老师的讲授~

T1

第一次想出正解

 

30 pts:

k <= 10,枚举如何把数放到矩阵中,O ( k ! );

 

100 pts:

对于矩阵的每一列,我们二分最小差异值,然后贪心去判断是否可行;

贪心策略:从前往后找,如果有从某个数开始往后连续的 m 个数,这 m 个数的最大值 - 最小值 < k,那么就把这 m 个数放到同一行,最后判断是否能够凑出 n 行;

std 标程:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 7;
int n, m, k, v[maxn];

int judge(int d)
{
    int tmp = 0;
    for (int i=1; i+m-1<=k; ++i)
    {
        if (v[i+m-1] - v[i] <=d)
            ++tmp, i += m - 1;
    }
    if (tmp >= n) return 1;
    return 0;
}

int main()
{
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    scanf("%d%d%d", &k, &n, &m);
    for (int i=1; i<=k; ++i)
        scanf("%d", &v[i]);
    sort(v + 1, v + k + 1);
    int left = 0, right = 1e9;
    while (left < right)
    {
        int mid = (left + right) / 2;
        if (judge(mid))
            right = mid;
        else
            left = mid + 1;
    }
    printf("%d\n", left);
    return 0;
}

我的拙码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
    char ch=getchar();
    int a=0,x=1;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') x=-x;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        a=(a<<1)+(a<<3)+(ch-'0');
        ch=getchar();
    }
    return a*x;
}
const int N=5e5;
int n,k,m,l,r=-1e9,ans;
int val[N];
bool check(int x)             //每行最大值减去最小值都要小于等于x 
{
    int tot=0;                //我们能匹配到tot行了 
    for(int i=1;i+m-1<=k;i++)
    {
        if(val[i+m-1]-val[i]<=x) //中间的点都可以选在同一行,那么两头的分别就是最大最小值 
        {
            tot++;
            i=i+m-1;
        }
        if(tot==n) return 1;
    }
    if(tot<n) return 0;
    else return 1;
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    k=read();n=read();m=read();
    for(int i=1;i<=k;i++)
    {
        val[i]=read();
        r=max(r,val[i]); 
    }
    sort(val+1,val+1+k);
    l=0;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) r=mid,ans=mid;
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}

 

T2

 

30 pts:

枚举分割点的位置,然后一顿瞎搞,O ( n ! ) ;

60 pts:

我们完全可以用 dp 来做(然后我就写炸了。。。)

我们先预处理出每一段的或和, 用 sum [ i ][ j ] 存起来;

f [ i ][ j ] 表示考虑了前 i 个数,分成 j 段的最大和 。

考虑转移:

f [ i ][ j ] = max ( f [ i ][ j ] , f [ l ][ j-1 ] + sum [ l+1 ][ i ];

 

100 pts:

我们考虑去优化 dp;

 

我们发现两个数组具有单调性: 

f [ l ][ j-1 ] 随着 l 的增加递增;

sum [ l+1 ][ i ] 随着 l 的增加而递减;

对于固定的 i,sum [ k+1 ][ j ] 的取值最多只有 32 种,而且 f 数组的值单调递增。预处理出转移点即可。

时间复杂度 O ( n * k * log C ),C 为 v [ i ] 的上界

100+ pts:

时间复杂度 O ( n k ) ? O ( n log C ) ? 欢迎补充

B_extended:将最大值改为最小值,怎么做?

 

 

T3

 

    

 

 

令 n = 2, C ( x , y ) 为在 x 个物品中选择 y 个不同的物品的方案数,树的最底层为 0 。

30 pts:

k <= 3,也就是说 n <=8 ,我们可以直接枚举 n 的全排列,把所有的情况加起来!

60 pts:

k <= 10,n <= 1024;

求出所有情况的魔法值;

考虑:两个点 x 和点 y 在第 d 层对答案的贡献;

算清楚 x 和 y 在第 d 层相遇了多少次:Σ(v [ x ] * v [ y ] * times [ x ][ y ][ d ]);

不妨考虑 2d - 1 个编号小于 y 的;

 

这才 60 pts 就已经晕了,那么接下来讲 100pts 的:

更改求和顺序,改为 2 * 2k! * 2k! * ( n - 2k+1 ) ! * C ( y-1 , 2- 1 ) * v [ y ] * C ( x - 1 - 2,  2^k-1) * v [ x ] ,枚举 k 和 y,我们知道 x >= max ( 2k+1 ,  y+1 ),先对 C ( x - 1 - 2,  2- 1 ) * v [ x ] 求后缀和即可。时间复杂度 O ( n * k );

 我们可以预处理:

 

 

 

 

 

数论

 

 

 

 

 

 

 

 

 

 

 

POJ 3735  Training little cats

有 n 只猫,有三种操作:

1、让第 i 只猫花生数 +1;
2、吃光第 i 只猫拥有的花生;
3、交换两只猫拥有的花生;
给出一个长度为 k 的操作序列,求将这个操作序列循环 m 次之后,每只猫拥有的花生数量; 

题解:

在线性代数中,矩阵乘法可以表示向量的变换;

将 n 只猫拥有的花生数量看成一个列向量;

操作1:向量的平移变换;

操作2:向量的投影变换;

操作3:向量的旋转变换;

找出每种操作对应的矩阵,依次做乘法即可;

 

考虑到 n 的范围太大, O ( n ) 的算法不大行,我们要想 log n 的算法;

自然想到了快速幂,我们用矩阵快速幂试试:

 

考虑到 k 是在不断变化的,但是最多就 18 种,所以我们做 18 次矩阵快速幂就好了,总时间复杂度 O(18 * 33 * log n);

 

欧几里得算法

给定数 a 和数 b,求两个数的最大公约数;

欧几里得算法(辗转相除法)

gcd(a , b)= gcd(b , a%b);

时间复杂度 O(log C);

扩展欧几里得的算法

求 ax + by = gcd(a,b)的一组整数解;

或者判断 ax + by = k 是否有解;

 

 

 

 

 

P1516 青蛙的约会

 

题解:

 

 

最小公倍数

 

 判断素数

给定一个数 n,判断 n 是否为素数;

 

筛素数

给定一个n,判断 1—n 这 n 个数哪些是素数;

N ≤ 106

 

用朴素的方法一个一个判断不可行;

只要一个数是某个质因数的 k 倍(k > 1),那么这个数就是合数;

数组 flag 表示每个数是不是素数;

如果一个数是素数,则这个数的倍数都是合数;

算法复杂度估计:O ( n ) – O ( n log n );

实际算法复杂度:O ( n loglog n );

 

线性筛素数 

普通筛素数的方法里,一个合数有可能会被重复筛去多次,因此效率不高;

改进思想:尽量少重复筛素数;

先贴上代码:

为什么时间复杂度是 O ( n )?

需要证明的东西:

1、我们不会重复删掉一个合数;

2、1~n 的合数都会被我们找出来;

 

对于一个合数,肯定能表示成:一个数 * 一个小素数 的形式;

因此所有的素数都能被我们筛出来;

算法正确性可以证明;

 

 

欧拉函数 

 

 

欧拉函数:给定数 n,求小于等于 n 中与 n 互素的数的个数;

等价于求 φ ( n );

等价于求 n 的质因数分解;

O ( √n );

 

 

线性求欧拉函数

给定一个数 n,要求 1-n 中所有数的欧拉函数;

利用欧拉函数的积性:

性质5:若 a、b 互质,则 φ ( a * b ) = φ ( a ) * φ ( b );

a % b == 0 , φ ( a * b ) =φ ( a ) * b;

 

 

 

费马小定理&欧拉定理

 

 

逆元

 

 

求逆元

 

 

线性求逆元

给定素数 p,求 1~p-1 中每个数在模 p 意义下的的逆元;

 

 

 

 

BZOJ 2705 [SDOI2012] Longge的问题

题目描述:Longge 的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数 N,你需要求出 ∑ gcd ( i , N ) ( 1 <= i <= N )。

对于 60% 的数据,0< N <= 216 

对于 100% 的数据,0 < N <= 232 

题解:

 

 

组合数 

 

杨辉三角 

 

 

二项式定理

 

 

同余

 

 

 

组合数取模:问题一

 

题解:

 

 

问题二

 

题解: 

 

 

问题三

 

题解: 

P 为合数,对于 0~(p-1),不是每个数都有 ( mod p ) 意义下的逆元;

但是 n , m , p 都不大,考虑组合数的计算式的变形:

 

问题四

 

 

 

Lucas定理

 

 

 

 

 

 

 

 

 

问题五 

 

 

题解: 

Lucas 定理 + 中国剩余定理;

用 Lucas 定理后得到 k 个同余方程;

怎样合并这 k 个同余方程是我们要解决的问题;

 

中国剩余定理

 

 

问题六 

 

题解: 

扩展卢卡斯定理; 

 

[ZJOI2010]排列计数

 

题解:

对于一个 n 个元素的二叉堆,其左右儿子为根的对,大小是确定的;

那么设左儿子的对大小为 l,右儿子的对的大小为 r,r = n - l - 1;

为什么是 n - l - 1 呢?因为根也占一个元素;

设 f [ i ] 表示 i 个元素组成的二叉堆的方案数;

f [ n ] = C ( n-1 , l ) * f [ l ] * f [ r ] % p;

若 p 很大,直接做;

若 p 很小,1……p-1 的数是有逆元的;

Lucas 定理,注意 p 必须是素数才能用;

 

 

高斯消元

解方程组;

思想:利用加减消元法解方程;

 

 

[HNOI2013]游走

 

题解:

期望走过的次数越大的边,编号越小 ==> 要求总分的期望最小;

每个点的期望经过次数 ==> 求每条边的期望经过次数;

一条边 编号为 k,端点为(x,y)

p [ x ] 表示第 x 个点的期望经过次数;

du [ x ] 表示与 x 相连的点数;

那么低 k 条边的期望经过次数就是 p [ x ] * 1 / du [ x ] + p [ y ] * 1 / du [ y ];

假设 x 号店与 t1 , t, t3 ,..... tk 相连;

p [ 1 ] = p [ t1 ] / du [ t] + p [ t2 ] / du [ t2 ] + ...... + p [ tk ] / du [ tk ] + 1; 

p [ x ] = p [ t1 ] / du [ t] + p [ t2 ] / du [ t2 ] + ...... + p [ tk ] / du [ tk ] ;  

有了 n 个方程,n 个未知数,高斯消元;

 

 

大步小步算法 

 

 

 

 

课后作业:Bzoj2242:[SDOI2011]计算器

 

 

 

老师的手稿证明过程: 

 

 

NOIp 会涉及到的数学相关知识:

1. 快速幂;

2. 矩阵乘法;

3. GCD / exGCD;

4. 筛素数 / 素数判断;

5. 欧拉函数 / 质因数分解;

6. 逆元;

7. 组合数问题 / 卢卡斯定理 ;

8. 中国剩余定理;

9. 高斯消元;

标签:10,int,题解,素数,清北,du,pts,Day,2k
来源: https://www.cnblogs.com/xcg123/p/11624969.html