• test20190611 NOIP模拟赛


    题一:答题比赛

    【问题描述】
    YYH报名参加了一个特殊的电视问答节目。这个节目共有n个问题,每回答正确1题,YYH就会获得1分,而每当YYH连续答对k题,那么他的现有得分乘以2,注意答对第k题后,是先加1分到总分中,再把总分乘以2,此时连续答对题目计数器会清零。现在YYH成功对了m题,他想知道他的最小得分。因为这个数字可能很大,你只需要输出这个数对1,000,000,009取模的结果即可。

    【输入格式】
    仅一行,三个数n,m,k如题目描述。

    【输出格式】
    仅一行,一个数,YYH的最小得分。

    【输入输出样例1】
    exam.in
    5 3 2
    exam.out
    3

    【输入输出样例2】
    exam.in
    5 4 2
    exam.out
    6

    【样例解释】
    样例1答对第1、3、5题可以获得最低分3分;
    样例2只答错第4题,可以获得最低分4+2分。

    【数据范围】
    对于30%的数据,n,m,k<=10
    对于60%的数据,n,m,k<=1000
    对于100%的数据,2<=k<=n<=10^9,0<=m<=n


    这个显然是优先往后放k-1个空一格。然后前面不够了的就连续放就行了。证明这个结论也很简单。

    开始没取模,然后又有除0……然而我不想写数列递推或者矩阵乘法了,所以TLE了2个点。

    #include<bits/stdc++.h>
    #define co const
    template<class T>T read(){
    	T data=0,w=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
    	for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
    	return data*w;
    }
    template<class T>T read(T&x){
    	return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    
    co int mod=1e9+9;
    int mul(int x,int y){
    	return (ll)x*y%mod;
    }
    int add(int x,int y){
    	return (x+=y)>=mod?x-mod:x;
    }
    int main(){
    	freopen("exam.in","r",stdin),freopen("exam.out","w",stdout);
    	int n=read<int>(),m=read<int>(),k=read<int>();
    	int t=k>1?min(n-m,min(n/k,m/(k-1))):0;
    	m-=t*(k-1);
    	int ans=0;
    	for(;m;m-=k){
    		if(m<k){
    			ans=add(ans,m);
    			break;
    		}
    		ans=mul(2,add(ans,k));
    	}
    	printf("%d
    ",add(ans,t*(k-1)));
    	return 0;
    }
    
    

    题二:人类基因组

    【问题描述】
    L教授最近正在研究一个关于人类基因的项目,基因可以被看作一个长度为n的序列:A0,A1,......,An-1。对于这个基因序列循环移动k位之后,就可以得到一个新的基因序列为:Ak,Ak+1,…,An-1,A0,A1,…,Ak-1。当一个基因序列满足对于任意的前i(1<=i<=n)项和都满足不小于0,我们就称这个基因序列为优质基因序列。
    由于L教授最近工作比较繁忙,所以找到了正在实验室闲逛的你,你的任务就是帮L教授统计出所有优质基因序列的个数。

    【输入格式】
    第一行一个整数n,表示基因序列的长度。
    第二行n个整数,依次为A0,A1,......,An-1的值。

    【输出格式】
    输出仅一个整数,表示优质基因序列的个数。

    【输入输出样例1】
    genes.in
    3
    2 2 3
    genes.out
    3

    【样例1说明】
    3个元素的序列:2 2 3,循环移动情况如下:
    循环移动0位得到序列:2 2 3,前i项和分别为:2 4 7,符合条件;
    循环移动1位得到序列:2 3 2,前i项和分别为:2 5 7;符合条件;
    循环移动2位得到序列:3 2 2,前i项和分别为:3 5 7;符合条件;

    【输入输出样例2】
    genes.in
    5
    3 -1 2 -3 4
    genes.out
    2

    【数据范围】
    对于30%的数据,满足1<=N<=5,000
    对于50%的数据,满足1<=N<=10,000
    对于100%的数据,满足1<=N<=1,000,000,-1,000<=Ai<=1,000


    把前缀和拿出来推一推式子就行了。扫描维护最小值。

    开始把大于等于0看成大于0了。

    #include<bits/stdc++.h>
    #define co const
    template<class T>T read(){
    	T data=0,w=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
    	for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
    	return data*w;
    }
    template<class T>T read(T&x){
    	return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    
    co int N=1e6+1;
    int n,s[N];
    bool v[N];
    int main(){
    	freopen("genes.in","r",stdin),freopen("genes.out","w",stdout);
    	read(n);
    	for(int i=1;i<=n;++i) s[i]=s[i-1]+read<int>();
    	for(int i=n-1,mv=s[n];i>=0;mv=min(mv,s[i]),--i)
    		v[i]=mv>=s[i];
    	int ans=v[0];
    	for(int i=1,mv=s[1];i<=n-1;++i,mv=min(mv,s[i]))
    		ans+=v[i]&(mv+s[n]-s[i]>=0);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    题三:最短路径

    【问题描述】
    平面内给出 n 个点,记横坐标最小的点为 A,最大的点为 B,现在Zxd想要知道在每个点经过一次(A 点两次)的情况下从 A 走到 B,再回到 A 的最短路径。但他是个强迫症患者,他有许多奇奇怪怪的要求与限制条件:

    1. 从 A 走到 B 时,只能由横坐标小的点走到大的点。
    2. 由 B 回到 A 时,只能由横坐标大的点走到小的点。
    3. 有两个特殊点 b1 和 b2, b1 在 0 到 n-1 的路上,b2 在 n-1 到 0 的路上。
      请你帮他解决这个问题助他治疗吧!

    【输入格式】
    第一行三个整数 n,b1,b2,( 0 < b1,b2 < n-1 且 b1 <> b2)。n 表示点数,从 0 到 n-1 编号,b1 和 b2 为两个特殊点的编号。
    以下 n 行,每行两个整数 x、y 表示该点的坐标(0 <= x,y <= 2000),从 0 号点顺序给出。Doctor Gao为了方便他的治疗,已经将给出的点按 x 增序排好了。

    【输出格式】
    仅一行,输出最短路径长度(精确到小数点后面 2 位)。

    【样例输入】
    5 1 3
    1 3
    3 4
    4 1
    7 5
    8 3

    【样例输出】
    18.18

    【样例解释】
    最短路径:0->1->4->3->2->0

    【数据范围】
    20%的数据n<=20
    60%的数据n<=300
    100%的数据n<=1000
    对于所有数据x,y,b1,b2如题目描述。


    把回来那条路看成去的时候走两条路,然后变成了紫书上面一道题。

    由于这题有b1,b2的限制条件,所以状态不能减半。f[i,j]表示两终点情况下的最小值,并且要保证小于等于max(i,j)的点都走过了。转移只能往max(i,j)+1转移。

    还是DP比较熟练。

    #include<bits/stdc++.h>
    #define co const
    template<class T>T read(){
    	T data=0,w=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
    	for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
    	return data*w;
    }
    template<class T>T read(T&x){
    	return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    
    co int N=1e3;
    int n,b1,b2;
    #define x first
    #define y second
    pair<int,int> p[N];
    double dis(int a,int b){
    	return sqrt(pow(p[a].x-p[b].x,2)+pow(p[a].y-p[b].y,2));
    }
    double f[N][N];
    int main(){
    	freopen("paths.in","r",stdin),freopen("paths.out","w",stdout);
    	read(n),read(b1),read(b2);
    	for(int i=0;i<n;++i) read(p[i].x),read(p[i].y);
    	for(int i=0;i<n;++i) fill(f[i],f[i]+n,1e18);
    	f[0][0]=0;
    	for(int i=0;i<n-1;++i)for(int j=0;j<n-1;++j)if(f[i][j]<1e18){
    		int t=max(i,j)+1;
    		if(t!=b2) f[t][j]=min(f[t][j],f[i][j]+dis(i,t));
    		if(t!=b1) f[i][t]=min(f[i][t],f[i][j]+dis(j,t));
    	}
    	double ans=1e18;
    	for(int i=0;i<n-1;++i){
    		ans=min(ans,f[n-1][i]+dis(i,n-1));
    		ans=min(ans,f[i][n-1]+dis(i,n-1));
    	}
    	printf("%.2lf
    ",ans);
    	return 0;
    }
    

    165->290

  • 相关阅读:
    2019 icpc南昌全国邀请赛-网络选拔赛J题 树链剖分+离线询问
    Android小项目之十二 设置中心的界面
    【Mood-5】14条建议,使你的IT职业生涯更上一层楼
    【Android 界面效果15】Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
    单线程模型中Message、Handler、Message Queue、Looper之间的关系
    140个google面试题
    Android小项目之十一 应用程序的主界面
    Android小项目之十 应用程序更新的签名问题
    Android小项目之九 两种上下文的区别
    Android小项目之八 界面细节
  • 原文地址:https://www.cnblogs.com/autoint/p/11002021.html
Copyright © 2020-2023  润新知