[noip模拟赛2017.7.17]

模拟试题(四)

试题概览

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

题目来源 Zju topcoder

求和

题目描述

求 1^b+2^b+…+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\n",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\n");
    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\n",ans);
    }
    return 0;
}
/*
4
15 14
15 16
14 15
16 15


*/

转载于:https://www.cnblogs.com/Anoxiacxy/p/7201111.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值