zoukankan      html  css  js  c++  java
  • 暴力+组合数学+预处理+双指针——cf 1371E1+E2

    E1,暴力+组合数学 对每个x都求一遍就行

    /*
    在位置i的糖果数量是x+i-1, 所以先把minx和maxx确定下来
    当a数组递增排列时,minx=max(minx,ai-i+1)
    当a中最大值出现在第一位时,取到maxx=ai
    x遍历范围[max(0,minx),max(maxx,n)], 
    将ai-x,然后ai只能出现在i及以后,那么从大到小求一个乘积,如果碰到%p=0,就是不行 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define N 2005 
     
    ll n,p,a[N],maxx,minx;
    vector<ll>v;
     
    int check(ll x){
        ll b[N],mul=1;
        for(int i=1;i<=n;i++)b[i]=a[i]-x+1;
        for(int i=n;i>=1;i--){//值为b[i]的数只能在位置b[i]及以后 
            if(b[i]<=0)b[i]=1;
            mul=mul*(n-b[i]+1-(n-i));
            mul%=p;
            if(mul%p==0)return 0;
        }
        return 1;
    }
     
    int main(){
        cin>>n>>p;
        for(int i=1;i<=n;i++)cin>>a[i];
    /*    n=2000;p=1999;
        for(int i=1;i<=2000;i++)a[i]=i;
    */    minx=0,maxx=0;
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)
            minx=max(minx,a[i]-i+1);
        maxx=a[n];
        
        for(int i=minx;i<=max(maxx,n);i++)
            if(check(i))v.push_back(i);
        
        cout<<v.size()<<'
    ';
        for(auto x:v)cout<<x<<" ";
    } 

    E2 数据为1e5,像E1那样暴力肯定不行,要先预处理出一个数组b,bi=i-a数组中值<=i的个数,然后用双指针在上面跑

    #include<bits/stdc++.h>
    using namespace std;
    #define N 500005
    #define ll long long 
    
    ll n,p,a[N],minx,maxx;
    
    map<ll,ll>b;
    
    int main(){
        cin>>n>>p;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        minx=0;maxx=max(a[n]-1,n);
        for(int i=1;i<=n;i++)minx=max(minx,a[i]-i+1);
        for(int i=minx;i<=maxx+2*n;i++){
            int pos=upper_bound(a+1,a+1+n,i)-a-1;
            b[i]=i-pos;
            b[i]%=p;b[i]+=2*p;b[i]%=p;
        }
        
        ll p1=minx,p2=minx-1;
        map<ll,ll>mp;
        vector<ll>v;
        for(int x=minx;x<=maxx;x++){
            while(p2<x+n-1){
                ++p2;
                mp[b[p2]]++;
            }
            while(p1<x){
                mp[b[p1]]--;
                p1++;
            }        
            if(mp[x%p]==0)
                v.push_back(x);
        }
        
        cout<<v.size()<<'
    ';
        for(auto x:v)cout<<x<<" ";
    }
  • 相关阅读:
    使用CustomValidate自定义验证控件
    C#中金额的大小写转换
    Andriod出错之Unable to build: the file dx.jar was not loaded from the SDK folder!
    VC 编写的打字练习
    机房工作笔记Ping只有单向通
    web服务协同学习笔记(1)
    Dll 学习3 将MDI子窗口封装在DLL中
    机房工作学习文件共享
    Andriod出错之Failed to find an AVD compatible with target 'Android 2.2'
    Andriod出错之wrapper was not properly loaded first
  • 原文地址:https://www.cnblogs.com/zsben991126/p/13282786.html
Copyright © 2011-2022 走看看