11月20日——NOIP2016 day2(附code)

(同上一篇)PDF加密很严重……Nitor无法转成word,所以就委屈一下,我给你们我发的免费链接!!
http://pan.baidu.com/s/1hrCRTJm
http://download.csdn.net/detail/lemonoil/9706918
好了言归正传(博主好像就没有正经过……)
第一道题是要用前缀和的(然后我就写出来注释掉了……不知怎么的)
第二道题想手写堆然后GG,优先队列也GG,交了个sort上去[/哭]
第三题是状压dp(又是我最弱的dp……)(又听大神说splay可以……)交了个random嗯……
P.S.—–255的SC一等奖线也就不吐槽了………………
总之noip2016考爆了,回去不好交差了。

problem

#include <cstdio>
#include <algorithm>

using namespace std;

const int prime[8]={2,3,5,7,11,13,17,19};
int p[2009][8];
int n=2000,m=2000;
int cnt=0,x,y,kk,t;
int a[10],ans[2009][2009];
int main(){
    freopen("problem.in","r",stdin);
    freopen("problem.out","w",stdout);
    scanf("%d%d",&t,&kk);
    for (int i=1;i<=7;i++){
        if (prime[i]<=kk) cnt++;
    }
    for (int i=1;i<=n;i++){
        int tmp=i;
        for (int j=0;j<=cnt;j++){
            while(tmp % prime[j]==0)p[i][j]++,tmp/=prime[j]; 
        }
    }
    for (int i=0;i<=n;i++){
        int tmp=min(i,m);
        a[0]=a[1]=a[2]=a[3]=a[4]=a[5]=a[6]=a[7]=0;
        for (register int j=1;j<=tmp;j++){
            bool flag=1;
            for (register int k=0;k<=cnt;k++){
                a[k]+=p[i-j+1][k]-p[j][k];
                if (a[k]<p[kk][k]) flag=0;
            }
            if (flag) ans[i][j]++;
        }
    }
    for(int i=0;i<=n;i++){
        for (int j=1;j<=n;j++){
            ans[i][j]+=ans[i][j-1];
        }
    }
    for (int i=1;i<=n;i++){
        for (int j=0;j<=n;j++){
            ans[i][j]+=ans[i-1][j];
        }
    }
    while(t--){
        scanf("%d%d",&x,&y);
        printf("%d\n",ans[x][y]);
    }
}

earthworm

当知道答案是三个队列时,我崩溃了

#include <cstdio>
#include <algorithm>

using namespace std;

#define eps 1e-9
int n,m,q,u,v,t,x,y;
double p;
int a[100009],b[7000009],c[7000009],topa,topb,topc,curb,curc;
int main(){
    freopen("earthworm.in","r",stdin);
    freopen("earthworm.out","w",stdout);
    scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&t);
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i]+=m*q;
    }
    sort(a+1,a+1+n);
    int h=t;
    topb=topc=1,topa=n;
    for (int i=0;i<m;i++){
        h--;
        if (a[topa]>=b[topb] && a[topa]>=c[topc]){
            x=a[topa]-(m-i)*q;
            topa--;
            y=1ll*x*u/v;
            b[++curb]=y+(m-i-1)*q;
            c[++curc]=x-y+(m-i-1)*q;
        }
        else if (b[topb]>=a[topa] && b[topb]>=c[topc]){
            x=b[topb]-(m-i)*q;
            topb++;
            y=1ll*x*u/v;
            b[++curb]=y+(m-i-1)*q;
            c[++curc]=x-y+(m-i-1)*q;
        }
        else{
            x=c[topc]-(m-i)*q;
            topc++;
            y=1ll*x*u/v;
            b[++curb]=y+(m-i-1)*q;
            c[++curc]=x-y+(m-i-1)*q;
        }
        if (!h) h=t,printf("%d ",x);
    }
    putchar(10);
    h=t;
    for (int i=1;i<=n+m;i++){
        h--;
        if (a[topa]>=b[topb] && a[topa]>=c[topc]){
            x=a[topa];
            topa--;
        }
        else if (b[topb]>=a[topa] && b[topb]>=c[topc]){
            x=b[topb];
            topb++;
        }
        else{
            x=c[topc];
            topc++;
        }
        if (!h) h=t,printf("%d ",x);
    }
}

angrybirds

神奇的状压dp!!!

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <memory.h>
#include <cmath>

using namespace std;

#define eps 1e-6
#define mymin(x,y) ((x)<(y)?(x):(y))
int T,n,m,f[160],cnt;
double x[20],y[20];
int pcnt[(1<<18)+5];
bool cmp(int x,int y){
    int h=0;
    for (int i=0;i<n;i++){
        if (x & (1<<i)) h++;
        if (y & (1<<i)) h--;
    }
    return h<0;
}
int dp[(1<<18)+5],ans;
int main(){
    freopen("angrybirds.in","r",stdin);
    freopen("angrybirds.out","w",stdout);
    scanf("%d",&T);
    for (int i=0;i<(1<<18);i++){
        for (int j=0;j<=17;j++){
            if (i & (1<<j)) pcnt[i]++;
        }
    }
    while(T--){
        scanf("%d%d",&n,&m);
        ans=n,cnt=0;
        for (int i=1;i<=n;i++){
            scanf("%lf%lf",&x[i],&y[i]);
        }
        for (int i=1;i<=n;i++){
            for (int j=1;j<i;j++){
                if (fabs(x[i]-x[j])<=eps) continue;
                double a=(y[i]*x[j]-x[i]*y[j])/x[i]/x[j]/(x[i]-x[j]);
                if (a>=0) continue;
                double b=(y[i]-x[i]*x[i]*a)/x[i];
                int tmp=0;
                for (int k=1;k<=n;k++){
                    if (fabs(a*x[k]*x[k]+b*x[k]-y[k])<=eps) tmp|=1<<(k-1); 
                }
                f[++cnt]=tmp;
            }
        }
        for (int i=1;i<=cnt;i++){
            for (int j=1;j<=cnt;j++){
                if (i==j) continue;
                if ((f[i] & f[j])==f[i]) f[i]=0;
            }
        }
        sort(f+1,f+1+cnt,cmp);
        while(cnt && !f[cnt]) cnt--;
        memset(dp,0x3f,sizeof(dp));
        dp[0]=0;
        int full=(1<<n)-1;
        for (register int i=0;i<=full;i++){
            for (register int j=1;j<=cnt;j++){
                if (dp[i | f[j]]>dp[i]+1) dp[i|f[j]]=dp[i]+1;
            }
            ans=mymin(ans,dp[i]+pcnt[full^i]);
        }
        printf("%d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值