[noip模拟赛2017.7.17]

模拟试题(四)

试题概览

题目名称 求和 序列合并 Tower
提交文件 sum.* sequence.* tower.*
输入文件 sum.in sequence.in tower.in
输出文件 sum.out sequence.out tower.out
时间限制 1s 1s 1s
空间限制 128MB 128MB 128MB

题目来源 Zju topcoder

求和

题目描述

求 1b+2b+…+a^b 的和除以 10000 的余数

输入格式

第一行包含一个正整数 N 表示共有 N 组测试数据;
接下来 N 行,每行包含两个整数 a 和 b。

输出格式

共 N 行,每行一个对应的答案。

数据规模

对于 30%的数据,满足 N<=10,a,b<=1000;
对于 100%的数据,满足 N<=100,a,b<=1,000,000,000。

输入样例

1

2 3

输出样例

9

题解

对于a>10000的情况,不拿发现

    a^b=(amod10000)^b (mod10000)

所以,我们相当于只用处理10000以内的情况就行了

#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
const LL mod = 10000;
LL ksm(LL x,LL y){
	LL rtn;
	for(rtn=1;y;y>>=1,x=(x*x)%mod)
		if(y&1)rtn=(rtn*x)%mod;
	return rtn;
}
LL N,a,b;
int main(){
	freopen("sum.in","r",stdin);
	freopen("sum.out","w",stdout);
	scanf("%lld",&N);
	while(N--){
		scanf("%lld%lld",&a,&b);
		LL ans=0,sum=0;
		LL t=a/mod;
		LL s=a%mod;
		for(int i=1;i<=s;i++){
			LL rst=ksm(i,b);
			sum=(sum+rst)%mod;
			ans=(ans+rst)%mod;
		}
		if(t){
			for(int i=s+1;i<=mod;i++){
				LL rst=ksm(i,b);
				sum=(sum+rst)%mod;
			}	
			ans=(ans+(sum*t)%mod)%mod;
		}
		printf("%lld
",ans);
	}
	return 0;
}

序列合并

题目描述

有两个长度都为 N 的序列 A 和 B,在 A 和 B 中各取一个数相加可以得到 N^2 个和,求这 N^2 个 和中最小的 N 个。

输入格式

第一行一个正整数 N;

第二行 N 个整数 Ai,满足 Ai<=Ai+1 且 Ai<=10^9;

第三行 N 个整数 Bi,满足 Bi<=Bi+1 且 Bi<=10^9;

输出格式

仅一行,包含 N 个整数,从小到大输出这 N 个最小的和,相邻数字之间用空格隔开。

数据规模

对于 50%的数据,满足 1<=N<=1000;

对于 100%的数据,满足 1<=N<=100000。

输入样例

3

2 6 6

1 4 8

输出样例

3 6 7

题解

假想有n个队列,每个队列n个元素,第i个队列的第j个元素为(A[i]+B[j])
那么显然对于每个队列,其中元素都是单调递增的,那么我们把刚开始每个队列的开头放入一个优先队列,每次弹出一个最小值(A[i]+B[j]),找到该最小值所在的队列,将下一个可能成为答案的值(A[i]+B[j+1])丢入优先队列,重复n次,总复杂度O(nlogn)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;

int N,A[100100],B[100100],cnt;
struct node{
	int x,y;
	node (int xx=0,int yy=0){
		x=xx;y=yy;
	}
	friend bool operator < (node a,node b){
		return A[a.x]+B[a.y]>A[b.x]+B[b.y];
	}
};
priority_queue<node>q;
int main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	scanf("%d",&N);
	for(int i=1;i<=N;i++)scanf("%d",&A[i]);
	for(int i=1;i<=N;i++)scanf("%d",&B[i]);
	for(int j=1;j<=N;j++)
		q.push(node(1,j));
	while(true){
		cnt++;
		node k=q.top;q.pop();
		q.push(node(k.x+1,k.y));
		printf("%d",A[k.x]+B[k.y]);
		if(cnt==N)break;
	}
	return 0;
}

/*
3
2 6 6
1 4 8
*/
/*#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#define mod (10000)
using namespace std;

int N,A[100100],B[100100],cnt,ans[100100];
struct node{
	int x,y;
	node (int xx=0,int yy=0){
		x=xx;y=yy;
	}
	friend bool operator < (node a,node b){
		return A[a.x]+B[a.y]>A[b.x]+B[b.y];
	}
};

priority_queue<node>q;
vector<int>v[100100];
int main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	scanf("%d",&N);
	for(int i=1;i<=N;i++)scanf("%d",&A[i]);
	for(int i=1;i<=N;i++)scanf("%d",&B[i]);
	q.push(node(1,1));v[1].push_back(1);
	while(true){
		node k=q.top();q.pop();
		int i=k.x,j=k.y;
		ans[++cnt]=A[i]+B[j];
		printf("%d ",ans[cnt]);
		if(cnt==N)break;
		bool find=false;
		for(int e=0,sz=v[i].size();e<sz;e++)
			if(v[i][e]==j+1){
				find=true;
				break;
			}
		if(!find){
			q.push(node(i,j+1));
			v[i].push_back(j+1);
		}
		find=false;
		for(int e=0,sz=v[i+1].size();e<sz;e++)
			if(v[i+1][e]==j){
				find=true;
				break;
			}
		if(!find){
			q.push(node(i+1,j));
			v[i+1].push_back(j);
		}
	}
	return 0;
}
*/
/*
3
2 6 6
1 4 8
*/

Tower

题目描述

平面上有 N 个整数坐标点。如果将点(x0,y0)移动到(x1,y1),则需要的代价为|x0-x1|+|y0-y1|。 求使得 K(K=1,2,3….N)个点在同一位置上最小需要的代价。

输入格式

第一行包含一个正整数 N;
接下来 N 行,每行两个正整数 xi 和 yi,为第 i 个点的坐标,不超过 10^6。

输出格式

共 N 行,第 i 行为使得有 i 个点在同一位置的最小代价。

数据规模

对于 100%的数据,满足 1<=N<=50。

输入样例

4

15 14

15 16

14 15

16 15

输出样例

0

2

3

4

题解

本题是个暴力,外层枚举选择k个点的答案,然后枚举每一个可能成为最优值的点,计算出每个点离它的距离,然后找出最近的k个点,即为答案

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#define mod (10000)
#define INF (1<<30)
using namespace std;

struct Point {
	int x,y;
	Point (int xx=0,int yy=0){
		x=xx;y=yy;
	}
}p[100];
int px[100],py[100];
int N;int dis[100];
int main(){
	freopen("tower.in","r",stdin);
	freopen("tower.out","w",stdout);
	scanf("%d",&N);
	for(int i=1;i<=N;i++){
		scanf("%d%d",&p[i].x,&p[i].y);
		px[i]=p[i].x;
		py[i]=p[i].y;
	}
	printf("0
");
	for(int k=2;k<=N;k++){
		int ans=INF;
		for(int i=1;i<=N;i++)
			for(int j=1;j<=N;j++){
				int sum=0;
				for(int q=1;q<=N;q++)
					dis[q]=abs(px[i]-p[q].x)+abs(py[j]-p[q].y);
				sort(dis+1,dis+1+N);
				for(int q=1;q<=k;q++)
					sum+=dis[q];
				ans=min(sum,ans);
			}
		printf("%d
",ans);
	}
	return 0;
}
/*
4
15 14
15 16
14 15
16 15


*/

原文地址:https://www.cnblogs.com/Anoxiacxy/p/7201111.html