zoukankan      html  css  js  c++  java
  • 2021牛客寒假算法基础集训营2

    D 牛牛与整除分块

    题意

    给n,m两个数字,求n / m在n / i(i属于1~n)里面的整数从大到小排第几位

    比如 n=25 ,m=9 ,(25,12,8,6,5,4,3,2,1)答案是 8

    思路

    因为整除分块有一个对称性,两两相乘接近n,1~sqrt(n)-1是都有的,但sqrt(n)*(sqrt(n)+1)>=n的时候整除分块是偶数个,其他时候是奇数个

    比如20 sqrt(20)=4, 1 2 3 都有,按照对称性20,10,6,特判一下4*5==20,所以有两个数4和5

    比如19 sqrt(19)=4, 1 2 3 都有,按照对称性20,10,6,特判一下4*5>19,所以只有一个4

    #include<bits/stdc++.h>
    #define endl '
    '
    #define IOS ios::sync_with_stdio(false),cin.tie(0)
    #define mem(a,b) memset(a,b,sizeof a)
    #define pii pair<int,int>
    #define ll long long
    #define mod 1000000007
    const double pi = acos(-1);
    using namespace std;
    const int N = 1e5+10;
    const int modd=1e9;
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int n,x;
            scanf("%d%d",&n,&x);
            int k=(int)sqrt(n);
            int ge=2*k-1;
            if(k*k+k<=n){
                ge++;
            }
            if(x<k){
                printf("%d
    ",x);
            }
            else{
                printf("%d
    ",ge-n/x+1);
            }
        }
        return 0;
    }
    

    H 牛牛与交换排序

    题意

    牛牛有一个数组,数组元素是1到n的排列,即数组的值在1~n范围内,且每个数字仅出现1次。
    牛牛想要将该数组变为升序排列的,他可以进行如下的操作。

    首先他要确定一个长度k,k的范围在1~n之间。
    接下来他将会进行若干次操作。在每轮操作中他都可以选择一段长度为k的子数组,然后进行区间的翻转操作。

    他可以做任意次数的操作,但是要求他每次选择的子数组区间满足,并且区间长度等于一开始选定的k,也就是说一旦某一次操作选择了数组的某个位置进行区间翻转操作,下一次做区间翻转的位置将会比上一次更靠右。

    牛牛发现,并不总是存在一个k可以使得数组排序变为有序,请你告诉牛牛是否存在一个k能够在满足规则的情况下完成排序。

    思路

    数组从头开始,第一个下标和值不相等,值当前的下标-下标=k,然后如果不行则no,直接用reverse(比赛的时候死磕j,看到这题时候去吃饭了……)

    #include<bits/stdc++.h>
    #define endl '
    '
    #define IOS ios::sync_with_stdio(false),cin.tie(0)
    #define mem(a,b) memset(a,b,sizeof a)
    #define pii pair<int,int>
    #define ll long long
    #define mod 1000000007
    const double pi = acos(-1);
    using namespace std;
    const int N = 1e5+10;
    const int modd=1e9;
    int a[N];
    int b[N];
    int main(){
        IOS;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];b[a[i]]=i;
        }
        int flag=0;
        int len=0;
        for(int i=1;i<=n;i++){
            if(a[i]!=i){
                if(len==0){
                    len=b[i]-i;
                    reverse(a+i,a+i+len+1);
                }
                else{
                    if(a[i+len]==i){
                        reverse(a+i,a+i+len+1);
                        continue;
                    }
                    else{
                        flag=1;
                        break;
                    }
                }
            }
        }
        if(flag==1)
            cout<<"no"<<endl;
        else{
            cout<<"yes"<<endl;
            cout<<len+1<<endl;
        }
        return 0;
    }
    

    I 牛牛的“质因数”

    题意

    求和,求一个函数f[i],i范围1~n的和,f[i]这个函数,举个例子1500=22355*5,F(1500)=223555。因子从小到大排序

    思路

    我想了一个线性筛的方法,但因为范围可能到10^20次,所以开了int128,每次线性筛里面每个数遇到最多一次,素数不遇到,所以f[素数]=素数,那么f[非素数]=f[非素数] * 10^位数 + f[素数]

    #include<bits/stdc++.h>
    #define endl '
    '
    #define IOS ios::sync_with_stdio(false),cin.tie(0)
    #define mem(a,b) memset(a,b,sizeof a)
    #define pii pair<int,int>
    #define ll long long
    #define mod 1000000007
    const double pi = acos(-1);
    using namespace std;
    const int N = 4e6+10;
    const ll modd=1e10;
    int pri[N],a[N],tot=0,len[N];
    void print(__int128 x) {
    	if (!x) return;
    	if (x < 0) putchar('-'), x = -x;
    	print(x / 10);
    	putchar(x % 10 + '0');
    }
    ll zhi[N];
    void init(){
        for(int i=2;i<N;i++){
            if(!a[i]){
                pri[tot++]=i;
                zhi[i]=(ll)i;
            }
            ll cnt=1,k=zhi[i];
            while(k){
                cnt*=10;k/=10;
            }
            for(int j=0;j<tot&&i*pri[j]<N;j++) {
                a[i*pri[j]]=1;
                zhi[i*pri[j]]=zhi[pri[j]]*cnt+zhi[i];zhi[i*pri[j]]%=modd;
                if(i%pri[j]==0){
                    break;
                }
            }
        }
    }
    int main(){
        init();
        int n;
        scanf("%d",&n);
        ll sum=0;//cout<<(zhi[2097152])<<endl;
        for(int i=2;i<=n;i++){
            sum+=zhi[i];sum%=mod;
        }
        printf("%lld
    ",sum);
        return 0;
     }
    

    J 牛牛想要成为hacker

    题意

    给了一个暴力求这个数组能不能有三角形组成,出个hack的数据,要求循环min(C(3,n),n * n * lg(n))

    思路

    第一想法前面斐波那契数列,然后比赛直接挂机了……C(3,n)是骗人的,其实只要斐波那契倒着来后面全是1即可

    #include<bits/stdc++.h>
    #define endl '
    '
    #define IOS ios::sync_with_stdio(false),cin.tie(0)
    #define mem(a,b) memset(a,b,sizeof a)
    #define pii pair<int,int>
    #define ll long long
    #define mod 1000000007
    const double pi = acos(-1);
    using namespace std;
    const int N = 1e5+10;
    const int modd=1e9;
    int f[N];
    int main(){
        f[1]=2;f[2]=3;
        int n;
        for(int i=3;i<=40;i++){
            f[i]=f[i-1]+f[i-2];
        }
        for(int i=41;i<N;i++){
            f[i]=1;
        }
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            printf(i==n?"%d
    ":"%d ",f[i]);
        }
        return 0;
     }
    
  • 相关阅读:
    Sql 格式化日期
    shape 格式标准
    flex 状态
    flex 特效集
    invalidateProperties
    flex for循环
    关于继承
    win32常见寄存器register
    asm寻址方式
    java jni调用 非托管 dll
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/14390720.html
Copyright © 2011-2022 走看看