zoukankan      html  css  js  c++  java
  • 集训Day 2 2020.3.1 数论(质数与筛法)

    集训Day 2 2020.3.1 还是数论复习

    上节课作业

    1.酒桶移动

    三分!
    【此处期待题解】
    复杂度(O(nlog n))

    2.POJ2142:The Balanc

    有一天平和两种数量无限的砝码(重为(a)(b)),天平左右都可以放砝码,称质量为(c) 的物品,要求:
    放置的砝码数量尽量少;
    当砝码数量相同时,总质量尽量小。

    题解

    本质不就是(ax+by=c)吗,然后求(|x|+|y|)最小 且(|ax|+|by|)最小的可行解。
    不难想到可能满足第一条的只有(x)正整数最小解和y正整数最小解这两种解,其中一个 就是答案

    3.POJ2115:C Looooops

    for(i=A;i!=B;i+=C){i%=1<< k;}
    问:会循环多少次(有可能死循环)

    题解

    和跳青蛙差不多设(a=C),(b=2^k),(c=B-A)(ax+by=c)

    素数和筛法

    链接区:
    数论
    https://www.cnblogs.com/liuziwen0224/p/shulun1.html
    Day1集训
    https://www.cnblogs.com/liuziwen0224/p/xjx1.html

    判定素数

    int main(){
    	int n;
    	scanf("%d",&n);
    	for(int i=2;i<=n;i++){
    		int ok=0;
    		for(int j=2;j<sqrt(i);j++){
    			if(i%j==0) ok=1;
    		}
    	}
    	return 0;
    }
    

    埃氏筛

    复杂度(O(nloglog n))
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    1 2 3 / 5 / 7 / 9 / 11 / 13 / 15 / 17 / 19 /
    1 2 3 / 5 / 7 / / / 11 / 13 / / / 17 / 19 /(3)
    1 2 3 / 5 / 7 / / / 11 / 13 / / / 17 / 19 /(5)
    1 2 3 / 5 / 7 / / / 11 / 13 / / / 17 / 19 /(7)...

    bool he[10000005]={0};
    void Eratosthenes(int n){
    	for(int i=2;i<=n;i++){
    		if(he[i]) continue;
    		for(int j=2;j*i<=n;j++) he[j*i]=1;
    	}
    }
    

    例题讲解

    1.POJ2689:Prime Distance

    给不超过int的(l,r),其中(r-l+1 le 10^6),筛出其中的素数,并且求出相邻素数差值最大和最小的一对。

    题解

    1. 提示:区间内的合数的质因子一定有在50000以内的

    证明:如果不存在一个小于50000的,由于一个数至少有两个质因数,则大于50000的前两个质数(m,n)的乘积(mn>50000^2> ext {int})

    1. 筛出50000以内的素数,用它们来筛出[l,r]内的合数.
      怎么筛是个问题,假设我们有一素数(p)(并且筛完了素数(p)以前所有素数的倍数),我们显然希望找到第一个在区间内的素数的倍数,然后用筛法筛区间内的合数即可。

    2. 显然(p^2)是一个没被筛过的合数,如果(p^2<L),那么我们第一个筛的合数就应该是((l+p- 1)/p*p)(C++意义).
      如果(lle p^2 le r),那么第一个筛的合数就是(p^2),如果(p^2>r)那就不用筛了。
      然后对第一个筛的合数不断+p直到超过(r), 然后这些合数全筛走,剩下的就是质数.

    3. 其余细节也有很多,很有必要一写。

    2.POJ3421:X-factor Chains

    构造一个数列,起始为(1),终止为一给定数(X),满足(X_i < X_{i+1}) 并且(X_i | X_{i+1})。求出数列 最大长度和该长度下的情况数。((X<2^{20}))

    题解

    (X)分解质因数(假设有(n)个),要想最长显然它前面那个数是(n-1)个质因数相乘,那么再前面的那个数是(n-1)(n-2)个质因数相乘……以此类推,长度就是(n+1)(题要求输出此数(-1)
    即:
    (F)的质因数为(f_i)(n)个,构造(1,f_1,f_1f_2,f_1f_2f_3,...,X=prodlimits_{i=1}^nf_i)
    方案数就是有重元素的排列了

    3.CF449C:Jzzhu and Apples

    https://www.luogu.com.cn/problem/CF449C

    有数(1)~(n),要求配对,每对最大公约数不能为(1),求最大配对数。((nle 10^5)

    题解

    1. 贪心,显然有大素数因子的数难配对,于是从大到小枚举素数(p),那么(p,2p,3p)…… 都可以两两配对(前提是这个数没被配过)
    2. 那么如果一共是偶数个的话我们显然可以全配了。
    3. 如果是奇数个肯定要扔掉一个数。把(2p)扔掉,然后这些扔掉的数到了(p=2)的 时候就会自己互相配对啦。
    4. 不难发现我们最大化利用了每个数。

    (第一遍的时候的错误思路)
    筛到素数(p)(p)之后的所有倍数的个数(n),为偶数时情况数(ans=dfrac{n}{2}),奇数时把最后一个数留下,也许还有可能和别的配对,(p)从小到大遍历

    下期预告:中国剩余定理

    【此处留白】

    课后练习

    1.LGP2758 编辑距离

    设A和B是两个字符串。我们要用最少的字符操作次数,将字符串A转换为字符串B。
    这里所说的字符操作共有三种:
    1、删除一个字符;
    2、插入一个字符;
    3、将一个字符改为另一个字符;
    皆为小写字母

    题解

    由于对于字符串的操作只有4种情况(删除,添加、更改、不变),所以该题的子问题就是进行了这4种操作后的A字符串变为B字符串需要多少步。记录(dp_{i,j})的意义为把第一个字符串的1$i$位变为第二个字符串的1(j)位需要多少步

    转移方程
    1. 删:(dp_{i-1,j}+1)
      字符串A的前i-1个字符变为字符串B的前j个需要多少步[把字符串的第i个字符(最后一个)删除了],删除需要一步因此加1
    2. 添:(dp_{i,j-1}+1)
      (B_j)字符加在A字符串的最后面即添加,同样可以理解为将(B_j)字符删掉,因为不用再考虑了。字符串A的前(i)个字符变为字符串B的前(j-1)个需要多少步 添加需要一步因此加(1)
    3. 替:(dp_{i-1,j-1}+1)
      字符串A和B的最后两个都相等了,因此都不用再考虑。字符串A的前(i-1)个字符变为字符串B的前(j-1)个需要多少步 添加需要一步因此加(1)
    4. 不变:(dp_{i-1,j-1})
      字符串A和B的最后两个都相等,不考虑。
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    char s1[2005],s2[2005];
    int edit[2005][2005];
    int dp(int i,int j){ 
        if(edit[i][j]!=-1) return edit[i][j]; 
        if(i==0) return edit[i][j]=j;
        if(j==0) return edit[i][j]=i;
        int bonus=1;
        if(s1[i]==s2[j]) bonus=0;  
        return edit[i][j]=min(min(dp(i-1,j)+1,dp(i,j-1)+1),dp(i-1,j-1)+bonus);
    }
    int main(){
        scanf("%s
    %s",s1+1,s2+1);
        memset(edit,-1,sizeof(edit));
        int len1=strlen(s1+1),len2=strlen(s2+1);
        dp(len1,len2);
        printf("%d",edit[len1][len2]);
        return 0;
    }
    

    贴上大神吴昊恒博客及代码:
    https://www.luogu.com.cn/blog/arookieoier/post-20200301-ji-xun-lian-xi-ti

    2.JSK43511

    https://nanti.jisuanke.com/t/43511

    给两个由az和09组成的字符串,你可以 对任意一个字符串做如下操作:

    1. 在一个地方插入一个字母
    2. 删除一个字母
    3. 删除一个数字(k),然后在此处插入(k)个字母
      问最少几步使得两个字符串相同且没有数字存在?
      第一个字符串长10000,第二个长1000, 数字最多100个

    题解

    【待补充】

    要做就做南波万
  • 相关阅读:
    Redis常用数据类型及应用场景之Set
    Redis常用数据类型及应用场景之List
    Redis常用数据类型及应用场景之Hash
    exists & not exists
    oracle 中 dblink 的简单使用
    DockerCompose之数据卷Volume
    DockerCompose之常见编排脚本
    160308-学习State Pattern Actor
    12.3-框架维护
    12.2-机器人协作系统
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/xjx2.html
Copyright © 2011-2022 走看看