zoukankan      html  css  js  c++  java
  • NOIP2016提高组题解

    (D1T1) 玩具谜题((OK))

    (D1T2) 天天爱跑步

    (D1T3) 换教室((OK))

    (D2T1) 组合数问题((OK))

    (D2T2) 蚯蚓((OK))

    (D2T3) 愤怒的小鸟((OK))

    (2016)年的只有一道毒瘤题没做(!!!)

    (D1T1)简单模拟就好,字符串(名字/职业)与数字编号的映射直接用(map)就好.然后朝内向左=朝外向右,朝内向右=朝外向左.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    map<int,string>rev;
    const int N=1e5+5;
    int cx[N];
    int main(){
    	int n,m;cin>>n>>m;
    	for(int i=1;i<=n;++i){
    		int x;cin>>x;string s;cin>>s;
    		rev[i]=s;cx[i]=x;
    	}
    	int now=1;
    	while(m--){
    		int x,y;cin>>x>>y;
    		if(!x){
    			if(!cx[now]){
    				now-=y;if(now<=0)now+=n;
    			}
    			else{
    				now+=y;if(now>n)now-=n;
    			}
    		}
    		else{
    			if(!cx[now]){
    				now+=y;if(now>n)now-=n;
    			}
    			else{
    				now-=y;if(now<=0)now+=n;
    			}
    		}
    	}
    	cout<<rev[now]<<endl;
        return 0;
    }
    
    

    (D1T2)咕咕咕

    (D1T3)不久前谢总讲概率期望的时候写过.博客

    (D2T1)因为每一次的(k)都是不变的,然后看一下数据范围猜测一下是(n^2)预处理.然后组合数是可以递推的,因为(sum_{i=0}^nsum_{j=0}^i)是一个三角矩阵,所以我们递推出(f[i][j])表示(C_i^j)之后(处理的时候就取模),可以用二维前缀和来维护(f[i][j]=0)的数量(就如果取模之后等于零,就把矩阵中的这个位置赋值为(1),其它都是(0),然后就可以二维前缀和处理了).感觉讲的不是很清楚,代码还是很好懂的.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
     #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=2005;
    int f[N][N],g[N][N],sum[N][N];
    int main(){
    	int T=read(),k=read();
    	f[0][0]=1;
    	for(int i=1;i<=2000;++i){
    		f[i][0]=1;
    		for(int j=1;j<=i;++j){
    			f[i][j]=(f[i-1][j-1]+f[i-1][j])%k;
    			if(!f[i][j])g[i][j]=1;
    		}
    	}
    	for(int i=1;i<=2000;++i)
    		for(int j=1;j<=2000;++j)
    			sum[i][j]=g[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
    	while(T--){
    		int n=read(),m=read();
    		printf("%d
    ",sum[n][m]);
    	}
        return 0;
    }
    
    

    (D2T2)写了整整一个晚上.

    讲个笑话:

    刚开始好不容易才写出个(mlog_m)的算法,以为就是正解,结果交上去(T)(3)个点,心想:肯定是(pq)的常数大了,先不开(O_2),先自己卡一下常.

    然后就去卡了半个小时的常,发现还是(T)(3)个点.

    最后自信满满地开了一波(O_2),心想肯定能过,结果还是(T)(3)个点.

    然后再去仔细看一下数据范围,才发现(mlog_m)根本过不了.正解必须是(O(n))的.

    (lyh):(85)分都是送分的啊,直接开一个堆或者(multiset)来模拟整个过程就好了.

    (我写个堆的做法,还写了一个多小时,太菜了~~~)

    讲正解.发现题目隐藏的单调性,就是我们每次选当前最大的拎出来,拆成两个部分,一个部分大,一个部分小,然后两个部分分开来看,在每个部分中,先拆出的一定总是比后拆出的大.

    所以我们可以把堆换成三个数组(一个是初始的蚯蚓数组,一个是拆成的较小的那一部分,一个是拆成的较大的那一部分),三个数组中的元素一定都是单调递减的,然后每次要选最大的元素的时候就比较三个数组的队头即可.

    先把(mlog_m)的做法放出来.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    priority_queue<ll>Q;
    int main(){
    	int n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
    	for(int i=1,st;i<=n;++i)st=read(),Q.push(st);
    	for(int i=1;i<=m;++i){
    		ll x=Q.top();Q.pop();x+=1ll*(i-1)*q;
    		if(!(i%t))printf("%lld ",x);
    		ll y=(ll)x*u/v;
    		Q.push(y-q*i);Q.push(x-y-q*i);
    	}printf("
    ");
    	for(int i=1;i<=n+m;++i){
    		if(!(i%t))printf("%lld ",Q.top()+1ll*m*q);
    		Q.pop();
    	}printf("
    ");
        return 0;
    }
    
    

    正解做法(获取性质之后就是一顿模拟了)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=1e5+5;
    const int M=7e6+5;
    int n,m,q,u,v,t;
    int a[N],q1[M],q2[M];
    inline int check1(int tim,int i,int j,int k){
    	int x=a[i]+(tim-1)*q,y=q1[j]+(tim-1-j)*q,z=q2[k]+(tim-1-k)*q;
    	if(x>=y&&x>=z)return 1;
    	if(y>=x&&y>=z)return 2;
    	return 3;
    }
    inline int check2(int tim,int j,int k){
    	int y=q1[j]+(tim-1-j)*q,z=q2[k]+(tim-1-k)*q;
    	if(y>=z)return 2;
    	return 3;
    }
    int main(){
    	n=read(),m=read(),q=read(),u=read(),v=read(),t=read();
    	for(int i=1;i<=n;++i)a[i]=read();sort(a+1,a+n+1,greater<int>());
    	int a1=1,l1=1,l2=1,r1=0;
    	for(int i=1;i<=m;++i){
    		int en;
    		if(a1<=n)en=check1(i,a1,l1,l2);//注意初始数组的数可能都用完了
    		else en=check2(i,l1,l2);
    		if(en==1){
    			int x=a[a1]+(i-1)*q;
    			if(!(i%t))printf("%d ",x);
    			int y=(ll)x*u/v;x-=y;//x*u会爆int
    			q1[i]=min(x,y);q2[i]=max(x,y);++a1;
    			continue;
    		}
    		if(en==2){
    			int x=q1[l1]+(i-1-l1)*q;
    			if(!(i%t))printf("%d ",x);
    			int y=(ll)x*u/v;x-=y;
    			q1[i]=min(x,y);q2[i]=max(x,y);++l1;
    			continue;
    		}
    		if(en==3){
    			int x=q2[l2]+(i-1-l2)*q;
    			if(!(i%t))printf("%d ",x);
    			int y=(ll)x*u/v;x-=y;
    			q1[i]=min(x,y);q2[i]=max(x,y);++l2;
    			continue;
    		}
    	}printf("
    ");
    	for(int i=1;i<=n+m;++i){
    		int en;
    		if(a1<=n)en=check1(i,a1,l1,l2);
    		else en=check2(i,l1,l2);
    		if(en==1){
    			if(!(i%t))printf("%d ",a[a1]+m*q);
    			++a1;
    		}
    		if(en==2){
    			if(!(i%t))printf("%d ",q1[l1]+(m-l1)*q);
    			++l1;
    		}
    		if(en==3){
    			if(!(i%t))printf("%d ",q2[l2]+(m-l2)*q);
    			++l2;
    		}
    	}printf("
    ");
        return 0;
    }
    
    

    (D2T3)不久前考过,今天借此发现了以前博客的一个锅.

  • 相关阅读:
    配置多个视图解析器
    在500jsp错误页面获取错误信息
    移动端浏览器监听返回键
    eclipse添加js智能代码提示
    js验证银行卡号 luhn校验规则
    免装版tomcat注册成windows系统服务方法
    微信公众号支付,为什么你找了那么多关于微信支付博客案例依然跑不通......两步带你完成支付,看完还做不出来你找我
    jsp自定义标签
    MyBatis动态传入表名
    配置tomcat允许跨域访问,cors跨域资源共享
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11772371.html
Copyright © 2011-2022 走看看