模拟试题(四)
试题概览
题目名称 | 求和 | 序列合并 | 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
*/