2019.8.10小结

满分:300

总分:210

T1:100

T2:85

T3:25

T1 组合数问题

一道sb题目,注意范围,可打表解决,打出杨辉三角,在用前缀和求解即可

代码(一维前缀和)

#include<bits/stdc++.h>
using namespace std;
int n,m,t,k,ans,a[2010][2010],b[2010][2010];
int main(){
	scanf("%d %d",&t,&k);
	a[0][0]=1%k;
	a[1][0]=1%k;
	a[1][1]=1%k;
	for(int i=2;i<=2005;++i){
		for(int j=0;j<=i;++j){
			a[i][j]=(a[i-1][j]+a[i-1][j-1])%k;
		}
	}
	for(int i=0;i<=2005;++i){
		for(int j=0;j<=i;++j){
			b[i][j]+=b[i][j-1];
			if(a[i][j]==0) b[i][j]++;
		}
	}
	while(t--){
		scanf("%d %d",&n,&m);
		ans=0;
		for(int i=0;i<=n;++i){
			int j=min(m,i);
			ans+=b[i][j];
		}
		printf("%d\n",ans);
	}
	return 0;
}

二维

#include<bits/stdc++.h>
using namespace std;
int n,m,t,k,a[2010][2010],b[2010][2010];
int main(){
	scanf("%d %d",&t,&k);
	a[0][0]=1;
	a[1][0]=1;
	a[1][1]=1;
	for(int i=2;i<=2005;++i){
		for(int j=0;j<=i;++j){
			a[i][j]=(a[i-1][j]+a[i-1][j-1])%k;
			if(a[i][j]==0) b[i][j]=1;
		}
	}
	for(int i=1;i<=2005;++i){
		for(int j=1;j<=2005;++j){
			b[i][j]=b[i][j-1]+b[i-1][j]-b[i-1][j-1]+b[i][j];
		}
	}
	while(t--){
		scanf("%d %d",&m,&n);
		n=min(n,m);
		printf("%d\n",b[m][n]);
	}
	return 0;
}

T2 蚯蚓


一道有趣的题目,首先想到合并果子,然而发现会超时,我们可以发现首先拿出来的切掉后比后拿出来切掉后还是还长,即满足单调递增,故建立三个队列即可。评测鸡吃了15分。。

代码

#include<bits/stdc++.h>
#define p u/v
using namespace std;
long long n,m,len,t,a,u,v;
const int maxn=1e7+10;
int line1[maxn],line2[maxn],line3[maxn];
int l1,l2,l3,r1,r2,r3;
bool cmp(int x,int y){
    return x>y;
}
int gots(int x){
    int a,b,c,d;
    a=b=c=d=-1;
    if(l1<=r1) b=line1[l1]+x*len;
    if(l2<=r2) c=line2[l2]+x*len;
    if(l3<=r3) d=line3[l3]+x*len;
    a=max(b,max(c,d));
    if(a==b) l1++;
    else{
        if(a==c) l2++;
        else l3++;
    }
    return a;
}
int main(){
    scanf("%lld %lld %lld %lld %lld %lld",&n,&m,&len,&u,&v,&t);
    for(int i=1;i<=n;i++) scanf("%d",&line1[i]);
    sort(line1+1,line1+1+n,cmp);
    r1=n;l1=l2=l3=1;
    for(int i=1;i<=m;++i){
        int x=gots(i-1);
        if(!(i%t)) printf("%d ",x);
        int a=x*p;
        int b=x-a;
        line2[++r2]=a-i*len;
        line3[++r3]=b-i*len;
    }printf("\n");
    for(int i=1;i<=m+n;++i){
        int x=gots(m);
        if(!(i%t)) printf("%d ",x);
    }
    return 0;
}

T3 愤怒的小鸟

一道状压dp题,但是竟然可以搜索搜过!!(儒雅随和),考试只会打表,照着数据打了25分,我太弱了。

代码(爆搜)

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
int T,n,m,ans;
double x[25],y[25],a[25],b[25];
bool book[25];
bool cheak(double a,double b){
    return (fabs(a-b)<eps);
}
int clu(){
    int tmp=0;
    for(int i=1;i<=n;++i){
        if(book[i]) tmp++;
    }
    return tmp;
}
void dfs(int c,int k){
    if(k+clu()>=ans) return;
    if(c>n){
        ans=k+clu();
        return;
    }
    bool flag=false;
    for(int i=1;i<=k;++i){
        if(cheak(a[i]*x[c]*x[c]+b[i]*x[c],y[c])){
            flag=true;
            dfs(c+1,k);
            break;
        }
    }
    if(!flag){
        for(int i=1;i<=n;++i){
            if(!cheak(x[i],x[c])&&book[i]){
                double a1=(x[i]*y[c]-y[i]*x[c])/(x[c]*x[i]*(x[c]-x[i]));
                double b1=(y[c]-x[c]*x[c]*a1)/x[c];
                if(a1<0){
                    a[k+1]=a1;
                    b[k+1]=b1;
                    book[i]=0;
                    dfs(c+1,k+1);
                    book[i]=1;
                }
            }
        }
        book[c]=1;
        dfs(c+1,k);
        book[c]=0;
    }
     
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%lf %lf",&x[i],&y[i]);
        }
        memset(book,0,sizeof(book));
        ans=n;
        if(m==1) ans=n/3+2;
        else if(m==2) ans=(2*n)/3+1;
        dfs(1,0);
        printf("%d\n",ans);
    }
} 

状压dp

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
int dp[262144],st[200],num;
double x[25],y[25];
int t,n,m;
bool cheak(double a,double b){
    return fabs(a-b)<eps;
}
void init(){
    memset(dp,0x3f,sizeof(dp));
    memset(st,0,sizeof(st));
    num=0;
    dp[0]=0;
    for(int i=1;i<=n;++i){
        for(int j=i+1;j<=n;++j){
            if(!cheak(x[i],x[j])){
                double a1=(x[i]*y[j]-y[i]*x[j])/(x[i]*x[j]*(x[j]-x[i]));
                double b1=(y[j]-a1*x[j]*x[j])/x[j];
                if(a1<0){
                    ++num;
                    for(int k=1;k<=n;++k){
                        if(cheak(a1*x[k]*x[k]+b1*x[k],y[k])){
                            st[num]|=(1<<(k-1));
                        }
                    }
                }
            }
        }
    }
}
void solve(){
    init();
    for(int s=0;s<(1<<n);++s){
        for(int i=1;i<=num;++i) dp[s|st[i]]=min(dp[s|st[i]],dp[s]+1);
        for(int i=1;i<=n;++i) dp[s|(1<<(i-1))]=min(dp[s|1<<(i-1)],dp[s]+1);
    }
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%lf %lf",&x[i],&y[i]);
        }
        solve();
        printf("%d\n",dp[(1<<n)-1]);
    }
    return 0;
}
posted @ 2019-08-26 21:06  End_donkey  阅读(96)  评论(0编辑  收藏  举报