zoukankan      html  css  js  c++  java
  • 10:26模拟赛

    预计得分:(100+30+30)
    实际得分:(100+0+20)
    实实际得分:(100+30+20)




    NOIP模拟赛

    Reverse

    题目描述

    0比1小,所以1个串中如果0全在1前面,这个串就比较和谐。对于1个只包含
    0和1的串,你每次可以将若干个0变成1,或者将若干个1变成0。那么,最少需要变多
    少次才能把保证所有的0在1前⾯呢?

    输入格式

    一个01串。

    输出格式

    一个数即答案。

    数据范围与约定

    对于(40\%)的数据 ,(lenleq 20)
    对于(70\%)的数据,(lenleq 1000)
    对于(100\%)的数据,(lenleq 10^5)



    做法:枚举0和1交界的位置
    利用前缀和统计答案。
    因为太水所以2分钟就做完了第一题

    #include<iostream>
    #include<cstdio>
    #define N 500005
    using namespace std;
    
    void read(int & s){
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar());
    	for(s=0;isdigit(ch);s=s*10+ch-'0',ch=getchar());
    }
    
    int n;
    int s[N],q[N];
    
    int main(){
    	freopen("reverse.in","r",stdin);
    	freopen("reverse.out","w",stdout);
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar());
    	for(;isdigit(ch);s[++n]=ch-'0',ch=getchar());
    	for(int i=1;i<=n;++i)
    		q[i]=q[i-1]+s[i];
    	int ans=0x3f3f3f3f;
    	int qqq=0;
    	for(int i=0;i<=n;++i){
    		qqq=0;
    		qqq+=q[i]+n-i-q[n]+q[i];
    		ans=min(qqq,ans);
    	}
    	printf("%d",ans);
    	return 0;
    }
    
    





    Number

    题目描述

    给定 ,求有多少数对(<x,y>)满足:
    (x,yin [1,n],x<y)
    (x,y)中出现的([0,9])的数码种类相同。

    输入格式1个整数 。

    输出格式输出1个数即答案。

    数据范围与约定

    对于(30\%)的数据,(nleq 10^3)
    对于(100\%)的数据,(nleq 10^7)



    做法:打表没打完而且代码只允许10KB而且只能过30%的数据
    而且暴力都能打30分
    所以这题打表失败了
    本来想用组合数的相关内容做
    但是不好维护而且代码应该会巨长巨恶心
    就没写



    正解思路:
    首先统计出每个数其所有拥有数位的信息
    因为产生<a,b>关系的数(A,B)其拥有的数码相同
    这个可以通过下述方式达到
    (S_n)表示(n)的数位信息

    [S_n=sum_{i=0}^{9} 2^i(n/10^kequiv ipmod{10}) ]

    则统计出所有数位相同的组数通过排列组合得出即可
    我们设某一数位$S$的数量为$sum_S$,则易知$sum_S=C_{sum_S}^2$
    因为每两个拥有数位S相同的数$a_1,a_2$
    a_1
    ot =a_2
    所以对于任意$a_i,a_jin S$,都有$a_i
    ot =a_j$
    所以总共的$<a_i,a_j>$的个数为$C_{sum_S}^2$
    所以最终答案为$sum_{i=1}^n C_{s_{S_i}}^2*s_{S_i}$
    其中n为所以不同数位的个数
    





    Wave

    题目描述

    给定一个长为(n)的数列,试求一个最长的不稳定波动子序列满足任意偶数项的
    值不小于其相邻两项的值,且相邻两项的差不大于(k)

    输入格式

    输入第一行两个正整数 ;
    第 n行 个非负整数描述这个数列。

    输出格式

    输出一个整数即答案。

    数据范围及约定

    对于(30\%)的数据,(nleq 10^3)
    对于(70\%)的数据,(nleq 10^5)
    对于(100\%)的数据,(nleq 2*10^6), 数列中的数不超过(2^{31}-1)



    做法:(O(n^2)dp)
    能过30的数据没问题
    但是说好的(30\%)数据(10^3)
    呢???怎么变(10^5)了……
    这个做法可以用线段树优化
    具体是用权值线段树维护
    正解是贪心
    考场上想到贪心
    然后开始YY
    有一段单增区间([l,r])
    答案应该存在于([l,r])的两端才对
    然后脑残的我竟然接着想如果([l,r])中存在一个很低的点
    亲手把我自己的假设抛弃了
    2333
    然后就抛弃了正解做法
    考后写了两份代码

    #include<iostream>
    #include<cstdio>
    #define N 2000007
    #define inf 0x7fffffff
    using namespace std;
    
    int s[N];
    int que[N];
    
    inline int read() {
    	int x=0;
    	char c=getchar();
    	while(c<'0'||c>'9')c=getchar();
    	while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();return x;
    }
    
    int main(){
    	int n=read();
    	int k=read();
        que[0]=inf;
        int now=0;
        for(int i=1;i<=n;++i)s[i]=read();
        for(int i=1;i<=n;++i){
            if(now&1){
        		if(s[i]>=que[now]+k)que[++now]=s[i];
        		if(s[i]<que[now])que[now]=s[i];
            }
            else {
        		if(s[i]+k<=que[now])que[++now]=s[i];
        		if(s[i]>que[now])que[now]=s[i];
    		}
        }
        printf("%d",now);
        return 0;
    }
    
    #include<iostream>
    #include<cstdio>
    #define N 2000007
    #define inf 0x7fffffff
    using namespace std;
    
    int n,k;
    int s[N];
    int que[N];
    
    inline void read(int & s){
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar());
        for(s=0;isdigit(ch);s=s*10+ch-'0',ch=getchar());
    }
    
    int main(){
    	read(n);read(k);
    	int now=1;
    	que[0]=inf;
    	s[n+1]=inf;
    	for(int i=1;i<=n;++i)read(s[i]);
    	for(int i=1;i<=n;++i){
    		if(now&1){
    			while(s[i]+k>que[now-1]){
    				if(s[i]>que[now-1])que[now-1]=s[i];
    				i++;
    			}
    			while(s[i+1]<s[i]&&i<n)i++;
    			if(que[now-1]<s[i]+k||i==n+1){
    				break;
    			}
    			que[now]=s[i];++now;	
    		}
    		else {
    			while(s[i]<que[now-1]+k){
    				if(s[i]<que[now-1])que[now-1]=s[i];
    				i++;
    			}
    			while(s[i+1]>s[i]&&i<n)i++;
    			if(s[i]<que[now-1]+k||i==n+1){
    				break;
    			}
    			que[now]=s[i];++now;
    		}
    	}
    	int ans=0;
    	printf("%d",now-1);
    	return 0;
    }
    
  • 相关阅读:
    javaScript 中的异步编程
    javaScript内存泄漏
    javaScript| 对象的拷贝
    javaScript 数组的拷贝
    javaScript 去除数组中的重复值
    解决js key中的时间间隔
    js未命题(杂记)
    js中斐波拉切数的三种写法;
    js闭包的七中形式
    Javascript学习日志(三):闭包
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/7737824.html
Copyright © 2011-2022 走看看