• 2020.07.15【NOIP提高组】模拟


    2020.07.15比赛总结

    最大配对

    题目大意:给出(2)个序列(A={a[1],a[2],…,a[n]},B={b[1],b[2],…,b[n]}),从(A、B)中各选出k个元素进行一一配对(可以不按照原来在序列中的顺序),并使得所有配对元素差的绝对值之和最大。例如各选出了(a[p[1]],a[p[2]],……,a[p[k]])(b[q[1]],b[q[2]],……,b[q[k]]),其中(p)序列中的元素两两不相同,(q)序列中的元素两两不相同,那么答案为(|a[p[1]]-b[q[1]]|+|a[p[2]]-b[q[2]]|+……+|a[p[k]]-b[q[k]]|),现在任务也就是最大化这个答案。

    这题非常的简单,只要你会快排,你就能立马想出来,用最大减最小。

    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    int a[100005],b[100005],n,k;
    
    int main()
    {
    	scanf("%d%d",&n,&k);
    	for (int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for (int i=1;i<=n;i++)scanf("%d",&b[i]);
    	sort(a+1,a+1+n);
    	sort(b+1,b+1+n);
    	int l1=1,r1=n,l2=1,r2=n;
    	long long ans=0;
    	for (int i=1;i<=k;i++)
    	{
    		if (abs(a[l1]-b[r2])>abs(a[r1]-b[l2]))
    		{
    			ans+=(long long)abs(a[l1]-b[r2]);
    			r2--;
    			l1++;
    		}
    		else
    		{
    			ans+=(long long)abs(a[r1]-b[l2]);
    			r1--;
    			l2++;
    		}
    	}
    	printf("%lld
    ",ans);
    }
    

    旅行

    题目大意:教主要带领一群Orzer到一个雄奇地方勘察资源。这个地方可以用一个n×m的矩阵A[i, j]来描述,而教主所在的位置则是位于矩阵的第1行第1列。矩阵的每一个元素A[i, j]均为一个不超过n×m的正整数,描述了位于这个位置资源的类型为第A[i, j]类。教主准备选择一个子矩阵作为勘察的范围,矩阵的左上角即为教主所在的(1, 1)。若某类资源k在教主勘察的范围内恰好出现一次。或者说若教主选择了(x, y)即第x行第y列作为子矩阵的右下角,那么在这个子矩阵中只有一个A[i, j](1≤i≤x,1≤j≤y)满足A[i, j]=k,那么第k类资源则被教主认为是稀有资源。
      现在问题是,对于所有的(x, y),询问若(x, y)作为子矩阵的右下角,会有多少类不同的资源被教主认为是稀有资源。
     为了照顾Vijos脑残的输出问题,设B[i, j]表示仅包含前i行与前j列的子矩阵有多少个数字恰好出现一次,那么你所要输出所有B[i, j]之和mod 19900907。

    正解DP
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    using namespace std;
    int n,a[5000],b[5000],f[5000][3];
    
    int main()
    {
    	scanf("%d",&n);
    	scanf("%d",&a[1]);
    	for (int i=2;i<=n;i++) scanf("%d",&a[i]),b[i]=b[i-1]+abs(a[i]-a[i-1]);
    	a[n+1]=a[n];
    	memset(f,120,sizeof(f));
    	f[n][0]=f[n][1]=0;
    	for (int i=n-1;i>=1;i--)
    	{
    		f[i][0]=min(f[i+1][0]+abs(a[i]-a[i+1]),f[i+1][1]+abs(a[i]-a[i+2]));
    		for (int j=i+1;j<n;j++)
    			f[i][1]=min(f[i][1],min(f[j+1][0]+abs(a[i]-a[j+1]),f[j+1][1]+abs(a[i]-a[j+2]))+abs(a[i]-a[j])+b[j]-b[i+1]);
    		f[i][1]=min(f[i][1],b[n]-b[i+1]+abs(a[i]-a[n]));
    	}
    	printf("%d",min(f[1][0],f[1][1]));
    }
    

    资源勘探

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int P=19900907;
    int n,m,x[2000005],y1[2000005],y2[2000005],ans=0;
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	for (int j=1;j<=m;j++)
    	{
    		int q;
    		scanf("%d",&q);
    		if (!x[q]) x[q]=i,y1[q]=j,y2[q]=m+1;
    		else
    		{
    			if (j<y1[q]) ans=(ans+(i-x[q])*(y2[q]-y1[q]))%P,x[q]=i,y2[q]=y1[q],y1[q]=j;
    			else if (j<y2[q]) ans=(ans+(i-x[q])*(y2[q]-j))%P,y2[q]=j;		
    		}
    	}
    	for (int i=1;i<=n*m;i++)
    		if (x[i]) ans=(ans+(n+1-x[i])*(y2[i]-y1[i]))%P;
    	printf("%d
    ",ans);
    }
    

    排列统计

    题目大意:对于给定的一个长度为n的序列{B[n]},问有多少个序列{A[n]}对于所有的i满足:A[1]~A[i]这i个数字中有恰好B[i]个数字小等于i。其中{A[n]}为1~n的一个排列,即1~n这n个数字在序列A[I]中恰好出现一次。数据保证了至少有一个排列满足B序列。

    这题考虑B序列的差值,非常神奇,(B_i -B_{i-1}=0,1,2)

    (f_i)表示到第(i)个数时的方案数
    情况(1)(B_i - B_{i-1}=0),因为(i)没有贡献,所以(f_i=f_{i-1})
    情况(2)(B_i - B_{i-1}=1),这时说明要么第(i)个数是(leq i),要么(1) ~ (i-1)中有一数是(=i),这是加法原理,所以(f_i=f_{i-1}*[(i-B_{i-1})+(i-B_{i-1}-1)])
    情况(3)(B_i - B_{i-1}=2),这时说明第(i)个数是(leq i)(1) ~ (i-1) 中有一数是(=i)都有,这是乘法原理,所以(f_i=f_{i-1}*(i-B_{i-1}-1)^2)
    最后(ans=f_n)

    但是,要用高精度。

    #include<cstdio>
    using namespace std;
    int f[50000];
    int n,a[50000],l;
    
    void mtlt(int k)
    {
    	int m=0;
    	for (int j=1;j<=l;j++)
    	{
    		f[j]=f[j]*k+m;
    		m=f[j]/10;
    		f[j]=f[j]%10;
    	}
    	while (m)
    	{
    		f[++l]=m;
    		m=f[l]/10;
    		f[l]=f[l]%10;
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	f[1]=1,l=1;
    	for (int i=2;i<=n;i++)
    	{
    		if (a[i]-a[i-1]==1) mtlt(i-a[i-1]+i-a[i-1]-1);
    		else if (a[i]-a[i-1]==2)mtlt((i-a[i-1]-1)*(i-a[i-1]-1));
    	}
    	for (int i=l;i>=1;i--) printf("%d",f[i]);
    }
    
  • 相关阅读:
    吴裕雄--天生自然C语言开发:共同体
    吴裕雄--天生自然C语言开发:结构体
    吴裕雄--天生自然C语言开发:字符串
    吴裕雄--天生自然C语言开发:函数指针
    吴裕雄--天生自然C语言开发:指针
    吴裕雄--天生自然C语言开发:enum(枚举)
    100个容器周边项目,点亮你的容器集群技能树
    论云时代最经济的APM工具的姿势
    “弹性裸金属服务器”到底有那些特性?
    弹性裸金属服务器服务于市场的技术概要分析
  • 原文地址:https://www.cnblogs.com/nibabadeboke/p/13306201.html
Copyright © 2020-2023  润新知