zoukankan      html  css  js  c++  java
  • 7.8 月赛补题+cf 569div2

    B(暴力

    Q:统计两个正整数t1 、 t2 之间的所有数的约数个数和S,给出的两个数t1、t2为10000000以内的正整数。

    A:暴力,在1到t2之间枚举因子r ,t2/r-t1/r 即t1~t2之间包含该因子的数的个数 ,求和即t1 、 t2 之间的所有数的约数个数和

    C(贪心,中位数

    Q:http://47.96.116.66/problem.php?cid=1385&pid=2

    A:关于改变中位数为目标值的贪心,修改次数最小的最优方案是 目标值大于当前中位数时,改变任意小于目标值的数为目标值;

    目标值小于当前中位数时,改变任意大于目标值的数为目标值; 直到中位数改变

    D(欧拉函数

    从原点选择任意方向射线,对于给定c,问在(x,y)(|x| <= N , |y| <= N)范围内有多少方向恰好有c个整点;

    1.由于对称性,只考虑 区域d:x〉=0 ,y〈=x 即可;

    2.对于每一区域,任意一点(x,y)与原点连线所经整点数目为:min(n/(x/gcd),n/(y/gcd))在区域d内有 y〈=x,min(n/(x/gcd),n/(y/gcd))可化简为 n/(y/gcd)

    3.由于(y/gcd)与(x/gcd)互质,对于满足n/(x/gcd)==c的x/gcd,所有比其小的与其互质的数可作为(y/gcd)的取值。可满足的方案数即x/gcd的欧拉函数phi(x/gcd);

    欧拉函数用欧拉筛递推求取。

    /*
    特性 :
    1.若a为质数,phi[a]=a-1;
    2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
    3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])
    */
    int m[n],phi[n],p[n],nump;
    //m[i]标记i是否为素数,0为素数,1不为素数;p是存放素数的数组;nump是当前素数个数;phi[i]为欧拉函数
    int main()
    {
            phi[1]=1;
        for (int i=2;i<=n;i++)
        {
            if (!m[i])//i为素数
            {
                p[++nump]=i;//将i加入素数数组p中
                phi[i]=i-1;//因为i是素数,由特性得知    
            }    
            for (int j=1;j<=nump&&p[j]*i<=n;j++)  //用当前已得到的素数数组p筛,筛去p[j]*i
            {
                m[p[j]*i]=1;//可以确定i*p[j]不是素数 
                if (i%p[j]==0) //看p[j]是否是i的约数,因为素数p[j],等于判断i和p[j]是否互质 
                {
                    phi[p[j]*i]=phi[i]*p[j]; //特性2
                    break;
                }
                else phi[p[j]*i]=phi[i]*(p[j]-1); //互质,特性3其,p[j]-1就是phi[p[j]]   
            }
        }
    }

    ac代码:

    include <bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <set>
    #include <vector>
    #include <stack>
    #include <map>
    #define inf 0x3f3f3f3f
    #define N 5000005
    #define mod 10000000007
    #define mem(a,x) memset(a,x,sizeof(a))
    #define ll long long
    #define exp 1e-8
    #define lowbit(x) (x&-x)
    #define rep(i,x,y) for(int i=x;i<=y;i++)
    using namespace std; 
    int tot=0 ,prime[N] ,isprime[N] ,phi[N];
    void geteuler( int maxn ){
         phi[1] = 1;
         mem( isprime ,1 );
         isprime[1] = 0;
         for( int i=2 ;i<=maxn ;i++){
            if( isprime[i]){
                prime[tot++] = i;
                phi[i] = i-1;
            }
            for( int j=0 ;j<tot&&prime[j]*i<=maxn ; j++){
                isprime[i*prime[j]] = 0;
                if( i%prime[j]==0 ){
                    phi[i*prime[j]] = phi[i]*prime[j];
                    break;
                 }
                phi[i*prime[j]] = phi[i]*phi[prime[j]];
            }
         }     
    }
     
    int main()
    {
        int m ,c;
        scanf("%d%d" ,&m ,&c);
        geteuler( N );
        ll ans = 0;
        for( int i=1 ;i<=m ;i++ ){
            if( m/i==c )ans += phi[i];
            if( m/i<c )break;
        }
        printf("%lld",ans*8);
        return 0;
    }
      

    F

    A: 即全错排公式 :

    2阶递推形式 :D(1) = 0, D(2) = 1. D(n) = (n-1) [D(n-2) + D(n-1)]

    1阶递推形式:D(1) = 0 , D(n) = nD(n-1)-(-1)^n

    cf569 div2:

    D (归纳推理,构造

    Q:给定一种方案 ,在每一次的位移(dx,dy)不重复使用的情况下,不重复的遍历n*m的区域

    A:当n==1时 ,易构造一种方案为:(1,1)->(1,n)->(1,2)->(1,n-1)->(1,3)......

          当n>1时,由之前的构造归纳出此时应该构造中心对称的走法

         rep( i ,1 ,(n+1)/2){
             if( i!=n+1-i )
                rep( j ,1 ,m){
                 printf("%d %d
    " ,i ,j);
                 printf("%d %d
    " ,n+1-i ,m+1-j);
                }
             else
                rep( j ,1 ,(m+1)/2){
                 printf("%d %d
    " ,i ,j);
                 if( j == m+1-j)break;
                 printf("%d %d
    " ,n+1-i ,m+1-j);
                }
         }
    

     E(线段树

    Q: 给你n个物品(每个物品一个)的价格和m个现在依次排在队里的人手上的钱,每个人都会尽可能把钱用完去买一样东西,即买当前物品中能买的价值最高的,不能买就不买走人,问m个人排完之后剩下的价值最高的物品价格是多少。

    A:题意即找出一个最大的商品价格x ,使得价格>=x的商品数量大于财产>=x的人数;

    以价格为操作区间,类似于前缀和,1到物品的价格区间+1操作,1到人手里钱的区间-1操作,查询只要有出现正的值,这个价格就可以成为一个备选的目标,由于需要找的是一个最大的值,所以在查询时要优先查右区间,再查左区间。

    #include<bits/stdc++.h>
    #define rep( i ,x ,y) for(int i=x ;i<=y ;i++)
    #define lson pos<<1
    #define rson pos<<1|1
    using namespace std;
    
    typedef long long ll;
    const int maxn= 1e6+5;
    int tree[maxn<<2] ,lazy[maxn<<2] ,n ,m;
    int a[maxn] ,b[maxn];
    
    inline void push_down( int pos){
        if( lazy[pos]){
            lazy[lson] += lazy[pos];
            lazy[rson] += lazy[pos];
            tree[lson] += lazy[pos];
            tree[rson] += lazy[pos];
            lazy[pos] = 0;
        }
    }
    
    inline void push_up( int pos ){
        tree[pos] = max( tree[lson] ,tree[rson]);
    //    cout<<pos<<" "<<tree[pos]<<endl;
    }
    
    void updata( int L ,int R ,int l ,int r, int pos ,int v ){
    //    cout<<L <<" "<<R <<" "<<pos<<endl;
         if( L>=l && R<=r){
             lazy[pos] += v;
             tree[pos] += v;
             return;
         }
         push_down( pos );
         int mid = (L+R)>>1;
         if( l <= mid ) updata( L ,mid ,l ,r ,lson ,v);
         if( r > mid ) updata( mid+1 ,R ,l ,r ,rson ,v );
         push_up(pos); 
         //cout<<L <<" "<<R<<" "<<l<<" "<<r<<" "<<v<<endl;
    }
    
    int query( int L ,int R ,int pos){
        if( L==R )return R;
        push_down( pos );
        int mid = (L+R)>>1;
        if( tree[rson]>0 ) return query( mid+1 ,R ,rson );
        //查询时优先查询右子树 
        return query( L ,mid ,lson );
    }
    
    int main( ){
        scanf("%d%d" ,&n ,&m);
        rep( i ,1 ,n)scanf("%d" ,&a[i]) ,updata(1 ,maxn ,1 ,a[i], 1 ,1);
        //商品价格区间标记+1 
        rep( i ,1 ,m)scanf("%d" ,&b[i]) ,updata(1 ,maxn ,1 ,b[i], 1 ,-1);
        //人手财产区间标记-1 
        
        int q;
        scanf("%d" ,&q );
        int op ,id ,v;
        while( q-- ){
            scanf("%d%d%d" ,&op ,&id ,&v );
            if( op==1 ){
                updata( 1 ,maxn ,1 ,a[id] ,1 ,-1 );
                //先取消原区间 
                updata(1 ,maxn ,1 ,v ,1 ,1 );
                //再更新新区间 
                a[id] = v;
            }
            else{
                updata(1 ,maxn ,1 ,b[id] ,1 ,1);
                updata(1 ,maxn ,1 ,v ,1 ,-1);
                b[id] = v;
            }
            if( tree[1] >0 )printf("%d
    " ,query(1 ,maxn ,1));
            else printf("-1
    ");
        }
        return 0;
    }
  • 相关阅读:
    前端优化
    Git基础使用
    【高可用架构】用Nginx实现负载均衡(三)
    【高可用架构】借助Envoy工具发布项目到多台服务器(二)
    【高可用架构】开发机上部署Deploy项目(一)
    【Linux系列】Centos7安装Samba并将工作区挂载到win(八)
    【Linux系列】Centos 7部署Laravel项目(七)
    【Linux系列】Centos 7安装 Redis(六)
    【Linux系列】Centos 7安装 Mysql8.0(五)
    gitlab服务器搭建
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11156507.html
Copyright © 2011-2022 走看看