• 乱搞及剪枝


    剪枝乱搞我觉得还是要总结一下的

    乱搞

    毛三琛

    正解是乱搞及剪枝

    随机化,用剪枝增多随机化次数

    #include<bits/stdc++.h>
    using namespace std;
    #define ll int
    #define A 44444
    ll n,mod,k,ans,maxx;
    ll a[A],b[A],p[A],q[A];
    ll random(ll x){
        return 1ll*rand()%x;
    }
    ll check(ll mid){
        ll cnt=1,sum=0;
        for(ll i=1;i<=n;i++){
            if(sum+b[i]<=mid){
                sum+=b[i];
            }
            else {
                sum=b[i];
                cnt++;
            }
            if(cnt>k) return 0;
        }
        return 1;
    }
    void work(){
        ll l=maxx,r=ans;
        ll nowans=0x7fffffff;
        while(l<=r){
            ll mid=(l+r)>>1;
            if(check(mid)){
                r=mid-1;
                nowans=mid;
            }
            else l=mid+1;
    //        if(l>ans) return ;
        }
        ans=min(ans,nowans);
    }
    int main(){
        ans=0;
        srand((unsigned)time(0));
        double st=clock();
        scanf("%d%d%d",&n,&mod,&k);
        for(int i=0;i<mod;++i)p[i]=i;
        random_shuffle(p+0,p+mod);
        random_shuffle(p+0,p+mod);
        random_shuffle(p+0,p+mod);
        random_shuffle(p+0,p+mod);
        random_shuffle(p+0,p+mod);    
        for(ll i=1;i<=n;i++)
            scanf("%d",&a[i]),ans+=a[i],maxx=max(a[i],maxx);
        for(int kx=1;kx<=mod;++kx){
            ll i=p[kx-1];
            maxx=0;
            double ed=clock();
            if((ed-st)/1e6>0.99) break;
            for(ll j=1;j<=n;j++)
                b[j]=(a[j]+i)%mod,maxx=max(maxx,b[j]);
            if(!check(ans)) continue ;
            work();
            
        }
        printf("%d
    ",ans);
    }
    View Code

    小P的生成树

    神仙生成树

    类似最小方差生成树

    然而可以用这种方法乱搞

        friend bool operator < (const node &c,const node &d){
            return c.a*k1+c.b*k2>d.a*k1+d.b*k2;
        }
            k1=random(20000)-10000,k2=random(20000)-10000;
            init();
            sort(edg+1,edg+m+1);

    SKYH的最短路

    有一些边权不确定,但不确定的边权全部相等,每个点能否在最短路上

    随机化,卡时==AC

    注意判断每个点能否在最短路

    可能有多条最短路径

    vector存一下跑拓扑排序

    最长不下降子序列

    $1e12$,有循环节

    循环接长度150

    正解太神了,我不会,神仙矩阵快速幂优化

    怎么乱搞?

    找出len*len循环节即可

    若n>len*len跑len*len,否则跑满n

    为什么是len*len

    这样能取遍循环节每一个元素

    即使出现1 2 3 4 5 6 这样循环节,我们也可以这样取出第一个循环节1,第二个循环节2,,,,,,,,,,,依次类推

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll n,t,a,b,c,d,kuku,maxn;
    struct node{
        ll l,r,val;
    }tr[8222222];
    void built(ll x,ll l,ll r){
        tr[x].l=l,tr[x].r=r;
        if(l==r){
            tr[x].val=0;
            return ;
        }
        ll mid=(l+r)>>1;
        built(x<<1,l,mid);
        built(x<<1|1,mid+1,r);
    }
    void change(ll x,ll pla,ll val){
        if(tr[x].l==tr[x].r){
            tr[x].val=val;
            return ;
        }
        ll mid=(tr[x].l+tr[x].r)>>1;
        if(mid>=pla)change(x<<1,pla,val);
        else change(x<<1|1,pla,val);
        tr[x].val=max(tr[x<<1].val,tr[x<<1|1].val);
    }
    void ask(ll x,ll l,ll r){
        if(tr[x].l>=l&&tr[x].r<=r){
            maxn=max(maxn,tr[x].val);
            return ;
        }
        ll mid=(tr[x].l+tr[x].r)>>1;
        if(mid>=l) ask(x<<1,l,r);
        if(mid<r)  ask(x<<1|1,l,r);
    }
    ll top;
    ll lis[22222222],vis[22222222];
    ll cnt=0,len,tot,lit,st,ans=0;
    int main(){
        scanf("%lld",&n);
        scanf("%lld%lld%lld%lld%lld",&t,&a,&b,&c,&d);
        ll mx=t;
        for(ll i=1;i<=n;i++){
            if(vis[lis[++tot]=t]){st=vis[lis[tot]];len=i-vis[t];lit=i-1;break;}
            vis[t]=i;
            t=(t*t*a+b*t+c)%d;
            mx=max(mx,t);
        }
        if(!st) st=n+1;
        lit=min(n,lit+len*len);
        for(ll i=st+len;i<=lit;i++){
            lis[i]=lis[i-len];
            tot++;
        }
        built(1,0,mx);
        for(ll i=1;i<=tot;i++){
            maxn=0;
            ask(1,0,lis[i]);
            change(1,lis[i],maxn+1);
            if(i>=st){
                ans=max(ans,(n-i)/len+maxn+1);
    //            printf("a[i]=%lld i=%lld n-i/len+maxn+1=%lld
    ",lis[i],i,(n-i)/len+maxn+1);
            }
            else ans=max(ans,maxn+1);
        }
        printf("%lld
    ",ans);
    }
    View Code

     

    贪心就是按照$b-a$从大到小排序,然后每次先取出a最大值,如果可以爬出就爬出,否则取出$b-a$继续爬

    然而不对

    2 999

    100 1

    900 800

    会先选900 800,然后选100 1

    显然不对

    然后SBLrefrain跟我BB说贪心是对的,可以微扰证明,我没过就是我个傻逼写错了

    他当时那种自大的神情我根本模仿不出来

    他说对拍700000组都没错,这个贪心一定是对的

    第二天我两组hack数据他都没过

    正解很神

    所以枚举角度无脑AC

    /*
    2 999
    900 800
    99 0
    2 
    2
    
    
    
    
    2but-1
    6 8
    4 2
    3 5
    3 4
    2 4
    6 3
    1 1
    1
    3
    2
    2
    3
    1
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define A 111111
    ll vis[A],c[A];
    ll ans=0x3f3f3f3f;
    ll n,l,zong,now,wwb;
    struct node{
        ll a,b,id;
        node(){}
        node(const ll &c,const ll &d,const ll &e){a=c,b=d,id=e;}
        friend bool operator < (const node &c,const node &d){
            return c.a<d.a;
        }
    }s[A];
    priority_queue<node> q;
    inline ll cmp1(const node &x,const node &y){
        return ((x.a-x.b)==(y.a-y.b))?(x.a<y.a):(x.a-x.b>y.a-y.b);
    }
    double delta=0;
    inline ll cmp5(const node &x,const node &y){
        return 1.0*x.a*delta-x.b>1.0*y.a*delta-y.b;
    }
    ll work(){
        memset(vis,0,sizeof(vis));
        now=0,wwb=0;
        while(!q.empty()) q.pop();
        for(ll i=1;i<=n;i++)
            q.push(s[i]);
        for(ll i=1;i<=n;i++){
            while(vis[q.top().id]) q.pop();
            if(now+q.top().a>=l) return i;
            vis[s[i].id]=1;
            now+=s[i].a-s[i].b;wwb+=c[i];
            if(now<=wwb) return 0x3f3f3f3f;
        }
    }
    void print(){
        if(ans==0x3f3f3f3f) puts("-1");
        else printf("%lld
    ",ans);
    }
    int main(){
        freopen("climb.in","r",stdin);
        freopen("climb.out","w",stdout);
        scanf("%lld%lld",&n,&l);
        for(ll i=1;i<=n;i++){
            scanf("%lld%lld",&s[i].a,&s[i].b);
            s[i].id=i;
        }
        for(ll i=1;i<=n;i++)
            scanf("%lld",&c[i]);
        for(double i=0;i<=1;i+=0.1){
            if(clock()>1800000){
                print();
                return 0;
            }
            delta=i;
            sort(s+1,s+n+1,cmp5);
            ans=min(work(),ans);
            if(clock()>1800000){
                print();
                return 0;
            }
        }
        print();
        return 0;
    }
    View Code

    剪枝

    打扫卫生

    打扫干净屋子再请客

    最优性剪枝

                if(nowcnt*nowcnt>f[i]) break;

    毛三琛

    剪枝比较显然,但没有见过,没有想到

    r越大符合可能性越高,如果check(r)都不符合,那么就一定不符合直接continue,,check下一个

    matrix

    最优性剪枝,可行性剪枝

    还有一种剪枝1 2 3 ,1 3 2 ,2 1 3都是一种方案,只枚举其中一种,

    因为是矩阵实现起来比较麻烦,但可以用id实现

    还有为了剪最优性的枝可以先sort贪心求出一种看似很优的解

     1 void dfs(ll sum,ll qs){
     2 //    printf("sum=%lld
    ",sum);
     3 //    printf("%lld
    ",ans);
     4     if(sum>=ans) return ;
     5     if(check()){
     6         ans=min(ans,sum);
     7 //        printf("ans=%lld
    ",ans);
     8         return ;
     9     }
    10     if(clock()>960000){
    11         printf("%lld
    ",ans);
    12         exit(0);
    13     }
    14     for(ll k=qs;k<=n*m;k++){
    15         ll i=tmp[k].x,j=tmp[k].y;
    16             if(!vis[i][j]){
    17                 if(ok(i,j)){
    18 //                    printf("enter %lld %lld
    ",i,j);
    19                     vis[i][j]=1;
    20                     ll x=i,y=j,
    21                     yuan1=now[x-1<1?1:x-1][y],
    22                     yuan2=now[x+1>n?x:x+1][y],
    23                     yuan3=now[x][y-1<1?1:y-1],
    24                     yuan4=now[x][y+1>m?y:y+1],
    25                     yuan5=now[x][y];
    26                     now[x-1<1?1:x-1][y]=1;
    27                     now[x+1>n?x:x+1][y]=1;
    28                     now[x][y-1<1?1:y-1]=1;
    29                     now[x][y+1>m?y:y+1]=1;
    30                     now[x][y]=1;
    31                     dfs(sum+val[i][j],k+1);
    32 //                    printf("hui %lld %lld
    ",i,j);
    33                     vis[i][j]=0;
    34                     now[x-1<1?1:x-1][y]=yuan1;
    35                     now[x+1>n?x:x+1][y]=yuan2;
    36                     now[x][y-1<1?1:y-1]=yuan3;
    37                     now[x][y+1>m?y:y+1]=yuan4;
    38                     now[x][y]=yuan5;
    39                 }
    40             }
    41     }
    42 }
    View Code
  • 相关阅读:
    C语言开发CGI程序的简单例子
    js收集错误信息,错误上报
    php安装pear、pecl
    (转)进程与线程的一个简单解释
    php curl 中的gzip压缩性能测试
    (转载):() { :|:& }; : # <-- 打开终端,输入这个,回车.你看到了什么??
    (转)open和fopen的区别:
    C语言中typedef
    secureCRT使用VIM 像LINUX中那样对语法高亮
    iframe与主框架跨域相互访问方法
  • 原文地址:https://www.cnblogs.com/znsbc-13/p/11720048.html
Copyright © 2020-2023  润新知