2016河海大学程序设计大赛专业组题解 快速幂取模 博弈论 背包 floyd

1035: UFO

时间限制: 1 Sec   内存限制: 128 MB
提交: 14   解决: 9
[ 提交][ 状态][ 讨论版]

题目描述

long long ago, there's a poor guy zyyyyy. one day he met a Huge Hovering UFO(HHU) and asked aliens in the HHU to make him rich, the aliens agreed and they gave him N problems to solve, and promised him if he solve problem i, he will get a[i] yuan for reward. However the aliens are evil, in fact they can get b[i] bytes of the knowledge of human beings if zyyyyy solve problem i. if they their knowledge sum up to more than M, they will explode the world. zyyyyy is very smart, he got the most money without exploding the world and made the aliens very angry. So can you figure out how can he do that?

输入

there are several test cases. every test case contains N + 1 lines:
line 1: N(1 <= N <= 3000), M(1 <= M <= 12000)
line 2..N+1: line i + 1 gives a[i] and b[i], (1 <= a[i] <= 400, 1 <= b[i] <= 100)
both N, M, a[i], b[i] are integers

输出

for each test case, output the money zyyyyy eventually got

样例输入

4 6
4 1
6 2
12 3
7 2

样例输出

23

提示

来源

//B
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<map>
using namespace std;
const int maxn =  12010;
int f[maxn];
int a[3010];
int b[3010];
int main(){
    int n,m,i,j;
    while(~scanf("%d%d",&n,&m)){
        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
        }
        for(i=1;i<=n;i++){
            for(j=m;j>=b[i];j--){
                f[j] = max(f[j-b[i]]+a[i],f[j]);
            }
        }
        printf("%d\n",f[m]);
    }
    return 0;
}

1036: HHU tower

时间限制: 1 Sec   内存限制: 128 MB
提交: 10   解决: 3
[ 提交][ 状态][ 讨论版]

题目描述

there is a tower in the universe's center - Hohai University, people call it HHU tower. HHU tower has 3 pillars(柱子). there is N plates(盘子) through these pillars which are labeled from 1 to N. HHU tower has a strange feature that for every pillar, plates with smaller index are always above plates with bigger index at any time. for example, plate i must be above plate i + 1 if they are placed through the same pillar. Originally, all the plates are placed through pillar 1, the big brother of HHU ask zyyyyy to move one plate from one pillar to the other(must satisfy HHU tower's feature) each day until all the plates are finally placed through pillar 3. zyyyyy is poor so he want to keep this job as long as possible. However the big brother know that zyyyyy may play trick so he can do this job forever so he ask zyyyyy to make sure that the pillars' state must not be repeated. zyyyyy knows the big brother is watching him, so please help him find how many days can he do this job at most?

输入

there are several test cases. each test case has one line with a integer N(1 <= N <= 10000)

输出

for each N, output the most steps need. the result can be very large so mod 10000007.

样例输入

1

样例输出

2

提示

origin state: the only pillar is through pillar 1

day 1: move the only plate from pillar 1 to pillar 2

day 2: move the only plate from pillar 2 to pillar 3, you can not move to pillar 1 again because that will repeat the origin state.

来源

这个是快速幂。。。然而公式是如何推出来的呢。。。

小萌学姐:

你看啊,这个总共有三个柱子n个盘子嘛,要求每次盘子的摆放状态都要不一样啊,而且还要取最大嘛,那就是3^n次方喽,结果要减一嘛,因为去掉最开始的那个状态

原来如此。。。。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <cstdlib>
#include <queue>
#include <stack>
using namespace std;
long long mod = 10000007;
long long queen(long long another){
    if(another==0){
        return 1;
    }else if(another==1){
        return 3;
    }
    long long res = 0;
    res = queen(another/2)%mod;
    res = (res * res)%mod;
    if(another%2){
        res = (res * 3 )%mod;
    }
    return res;
}
int main(){
    long long n;
    while (~scanf("%lld",&n)) {
        long long ans = queen(n);
        printf("%lld\n",(ans-1)%mod);
    }
    return 0;
}

1037: Calvin's Experiment

时间限制: 1 Sec   内存限制: 128 MB
提交: 2   解决: 2
[ 提交][ 状态][ 讨论版]

题目描述

Calvin Neo is a acmer in HHU, but he is also a civil engineer. Civil Engineering is about moving bricks(搬砖), however it involves many scientific theories and experiments.
Calvin designed a experiment to evaluate the attribute of soil in a construction site(工地), the construction site can be viewed as a 2-dimension Cartesian Coordinate System(平面直角坐标系), this experiment includes 2 steps:
1. Calvin choose some point and use CDT(a geological survey method) to test the attribute of soils at that point and use them to work out some assumptions.
2. Calvin choose n tested points from step 1 and get a polygon(多边形). he start from point 1 and go along the polygon, visit every point once and finally back to point 1. while walking, Calvin use geological radar(地质雷达) to detect the attribute of soils beneath to prove his assumptions
however life in Calvin's construction site is hard, there are ways between only several tested points and the geological radar is expensive so that Calvin should find a polygon with the shortest length(周长).
Calvin is a acmer and he definitely knows the answer, but he is busy moving bricks now, so he ask you for help.

输入

there are multiple test cases, every test case has multiple lines:
line 1: 2 integers n(less than 233), m(less than 500, for 70% cases, m less than 200)
following n lines: 2 integers x, y stand for the coordinate of points(start from 1), 0 <= (x, y) <= 1000
following m lines: 2 integers u, v means there is a path between u and v

输出

for every test case print one line, which is the minimum length(周长)
print "impossible" in one line if there is no such polygon
hint: you should use "%.2f\n" to print

样例输入

9 6
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
1 3
1 7
7 9
3 9
2 5
4 5
1 0
1 1

样例输出

4.00
impossible

提示

for case 1, choose point 1, 2, 4, 5 as a polygon whose length is 4.00

来源

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 250;
const double killme = 1e7;
const double eps = 1e-8;
double min_loop;
double mp[maxn][maxn];
double dis[maxn][maxn];
pair<double, double > save[maxn];
vector<int> final[510];

int n,m;
void init(){
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            if(i==j){
                mp[i][j] = 0.0f;
                dis[i][j] = 0.0f;
            }else{
                mp[i][j] = INF;
                dis[i][j] = INF;
            }
        }
    }
    for(i=1;i<=m;i++){
        final[i].clear();
    }
}
bool online(int x,int y,int x1,int y1,int x2,int y2){
    int min_x = min(x1,x2),max_x = max(x1,x2);
    int min_y = min(y1,y2),max_y = max(y1,y2);
    if(min_x>x||x>max_x||y<min_y||y>max_y){
        return false;
    }
    if((y1 - y2) *  (x - x1) == (y - y1) * (x1 - x2)){
        return true;
    }
    return false;
}
bool floyd(){
    min_loop = INF;
    int i,j,k;
    for(k=1;k<=n;k++){
        for(i=1;i<k;i++){
            for(j=i+1;j<k;j++){
                if(min_loop>mp[i][j]+dis[i][k]+dis[k][j]){
                    min_loop = mp[i][j] + dis[i][k]+dis[k][j];
                }
            }
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
            }
        }
    }
    if(min_loop>killme){
        return  false;
    }else{
        return true;
    }
 
}
bool compare(int a,int b){
    if(abs(save[a].first-save[b].second)==0){
        return save[a].second<save[b].second;
    }
    return save[a].first<save[b].first;
}
int main(){
    //cout<<online(18, 97, 99, 67, 18, 97)<<endl;
    int i,j;
    while (~scanf("%d%d",&n,&m)) {
        double a,b;
        for(i=1;i<=n;i++){
            scanf("%lf%lf",&a,&b);
            save[i] = make_pair(a, b);
        }
        init();
        int u,v;
        for(i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            for(j=1;j<=n;j++){
                if(online(save[j].first, save[j].second, save[u].first, save[u].second, save[v].first, save[v].second)){
                    final[i].push_back(j);
                }
            }
            sort(final[i].begin(), final[i].end(), compare);
            for(j=0;j < final[i].size()-1;j++){
                u = final[i][j];
                v = final[i][j+1];
                mp[u][v] = min(mp[u][v] , sqrt(pow(save[u].first-save[v].first,2)+pow(save[u].second-save[v].second,2)));
                mp[v][u] = mp[u][v];
                dis[u][v] = mp[u][v];
                dis[v][u] = mp[u][v];
            }
            
        }
        if(floyd()){
            printf("%.2lf\n",min_loop);
        }else{
            printf("impossible\n");
        }
    }
    return 0;
}


1038: The Smartest Guy in HHU

时间限制: 1 Sec   内存限制: 128 MB
提交: 11   解决: 5
[ 提交][ 状态][ 讨论版]

题目描述

Song and zyyyyy are all very smart guys in HHU and one day they asked Calvin to tell who is smarter. However later that day Song came to Calvin Neo, gave him some money and asked him to hard point(钦定) her to be smarter. Because the money was so much that Calvin no longer need to moving bricks(搬砖) to feed himself so they made a transaction.
The next day, Calvin introduce a game to Song and zyyyyy. In this game, Song and zyyyyy take turns to multiply an integer p by integer from 2 to 9. In each round, Song always starts with p = 1, does her multiplication, then zyyyyy multiplies the number, then Song and so on. Before a game starts, Calvin decides an integer 1 < n < 4294967295 and the winner is who first reaches p >= n. Because both Song and zyyyyy are smart, so they all play perfectly.
Calvin has some n, please help him decide which of them can make Song win.

输入

one line for one case with a integer n

输出

"yes" if Song can win, "no" otherwise

样例输入

162
17
34012226

样例输出

yes
no
yes

提示

zyyyyy and sxm are not real people

来源

小萌学姐:

哎呀给你一个数字,这个数字是目标,那上一个操作的人的最优解肯定是拿9乘以原先那个数字对不对,尽量把数字拉高嘛

那上上个人看自己快输了肯定要尽量拉低数字嘛,所以肯定选最小的2来乘以原先的数

那么把给我的数用18除到[0,18]的时候看一看到底是在[0,9]还是(9,18]就好了啊

嗯。。。。博弈论真是神奇啊

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <cstdlib>
#include <queue>
#include <stack>
using namespace std;
const double eps = 1e-8;
bool flag;
int main(){
    double n;
    bool flag;
    while(~scanf("%lf",&n)){
        flag = true;
        while (n>18.0) {
            n /= 18.0;
        }
        if(n<9.0||abs(n-9.0)<eps){
            flag = true;
        }else{
            flag = false;
        }
        if(flag){
            printf("yes\n");
        }else{
            printf("no\n");
        }
    }
    return 0;
}

1039: Zyyyyy和Song的闰年问题

时间限制: 1 Sec   内存限制: 128 MB
提交: 13   解决: 8
[ 提交][ 状态][ 讨论版]

题目描述

    某天,Zyyyyy和Song一起学习有关闰年的知识,他们觉得我们平时所说的闰年是有问题的,为什么呢?众所周知,闰年(Leap Year)是为了弥补因人为历法规定造成的年度天数与地球实际公转周期的时间差而设立的,补上时间差的年份为闰年。四季构成的一年,就是“回归年”,也称“太阳年”,即太阳中心从春分点再到春分点所经历的时间,1回归年=365.24219879日。而我们习惯性的每四年一闰年。
     Zyyyyy觉得“每四年一闰年”是有问题,按照一年365天计算的话,如果n年之后,多出来的日子满一天的话,这一年就该算作闰年。而Song觉得Zyyyyy才有问题,两人争执不休,于是找到了崇尚真理的你。
     在假设从公元0年开始的情况下,他们给定一个年份y,问你这个年份从真理的角度(即大佬Zyyyyy的角度)讲,是不是闰年。

输入

有多个测试案例,但不多于10组。
每个测试案例,只包含一个非负整型数字,代表询问的年份y,0<=y<=4000000。

输出

对于每个测试案例,如果是闰年输出Y,如果不是闰年输出N。

样例输入

0
2000
2002
2016

样例输出

N
N
Y
N

提示

来源

SL

这题是个啥玩意我还是没明白

//C
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<map>
using namespace std;
const double eps = 1e-8;
int main(){
    int y;
    while(~scanf("%d",&y)){
        int i;
        double now = 0;
        for(i=1;i<=y;i++){
            now+=0.24219879;
            if(now>1.0){
                now -= 1.0;
            }
        }
        if(now+0.24219879>1||abs(now+0.24219879-1)<eps){
            printf("Y\n");
        }else{
            printf("N\n");
        }
        //cout<<now<<endl;
    }
    return 0;
}

1040: 世纪难题“晚饭吃啥”

时间限制: 1 Sec   内存限制: 128 MB
提交: 23   解决: 12
[ 提交][ 状态][ 讨论版]

题目描述

   Zyyyyy和Song经常需要面对“晚饭吃啥”这个世纪难题,为了解决这个世纪难题,他们每次都需要一次比赛决定,比赛输的一方来决定“晚饭吃啥”。他们比赛的题目是这样的:

   现有“ABCDEFG”7种大写字母,每个字母表示一个得分,“ABCDEFG”分别代表1、2、3、4、5、6、7分。给定一个只包含这7种字母的字符串s,每人从s中选择连续的n个字母,并将这n个字母代表的分数相加作为得分,得分多的一方获胜。Song深知Zyyyyy智商爆表,所以她求助于你,希望你能写个程序帮助她每次都能获胜。

输入

有T个测试案例,0<=T<=10。

每个测试案例有两行输入,第一行输入两个正整数m和n,分别表示字符串的长度和选择时字母连续的个数;第二行输入一个长度为m的字符串s。

0<m<=100,0<n<=m。输入的字符串保证只含有题目中描述的7种大写字母。

输出

对于每个测试案例,输出最高的得分。

样例输入

3
7 3
ABCDEFG
7 3
DGAECBF
10 4
DFEGAGFDCB

样例输出

18
13
22

提示

来源

SL

//H
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;

int main(){
    int t,n,m,i;
    string in;
    //t = 'A';
    //cout<<t<<endl; 65
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&m,&n);
        cin>>in;
        int now = 0,res = 0;
        for(i=0;i<n;i++){
            now += in[i]-64;
            //cout<<in[i] - 64;
            //cout<<now<<endl;
        }
        res = now;
        for(i=n;i<in.length();i++){
            now -= in[i-n]-64;
            //cout<<in[i-n];
            now += in[i]-64;
            //cout<<in[i]-64<<endl;
            res = max(res,now);
        }
        printf("%d\n",res);
    }
    return 0;
}

1041: A-B

时间限制: 1 Sec   内存限制: 128 MB
提交: 18   解决: 8
[ 提交][ 状态][ 讨论版]

题目描述

    河海ACM队一个盛产情侣的地方,比如大腿Song和巨腿Zyyyyy。Song和Zyyyyy的ACM之路都是从A+B这样的水题开始的,然而他们早已厌倦了A+B这种无聊的题目,他们想来点改变,于是乎,想到了A-B问题。

    给出两个八进制的数字a,b,需要计算a-b的结果,也用8进制表示,如果结果是负数,你需要用负数形式输出而不是给出补数。

输入

第一行是一个整数T(1 <= T <= 1000), 代表数据组数。
每组数组只有一行,为包括两个八进制的数a,b,其中0 <= a, b < 2^32。

输出

输出a-b的结果。

样例输入

1
76 7

样例输出

67

提示

来源


//A
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<map>
using namespace std;
char res[100];
bool compare(string a,string b){
   if(a.length()>b.length()){
        return true;
   }else if(a.length()<b.length()){
       return false;
   }
   for(int i=0;i<=a.length();i++){
        if(a[i]>b[i]){
            return true;
        }else if(a[i]<b[i]){
            return false;
        }
   }
   return true;
}
int main(){
    int t,i;
    string a,b;
    scanf("%d",&t);
    while(t--){
        long long resa =0,resb = 0;
        //scanf("%lld%lld",&a,&b);
        cin>>a>>b;
        bool flag = false;
        if(!compare(a,b)){
            swap(a,b);
            flag = true;
        }
        int p = 0;
        int lena = a.length()-1;
        int lenb = b.length()-1;
        for(i=0;i<b.length();i++){
            if(a[lena-i]>=b[lenb-i]){
                res[++p] = a[lena-i] - b[lenb-i] ;
                //cout<<a[lena-i]<<" "<<b[lenb-i]<<endl;

            }else{
                res[++p] = 8 - (b[lenb-i]-'0') + a[lena-i]-'0';
                //cout<<b[lenb-i]-'0'<<" "<<a[lena-i]-'0'<<"   ";
                a[lena-i-1]--;
                //cout<<a[lena-i-1]<<endl;
            }
        }
        for(i=a.length()-b.length()-1;i>=0;i--){
            res[++p] = a[i]-'0';
            //cout<<"tes "<<a[i]<<endl;
        }
        //cout<<"p"<<p<<endl;
        while(res[p]==0&&p>=0){
                p--;
        }

        if(p==-1){
            printf("0\n");
            //cout<<"aaa\n";
            continue;
        }
        if(flag){
            printf("-");
        }
        for(i=p;i>=1;i--){
            printf("%d",res[i]);
        }
        printf("\n");
    }
    return 0;
}

1042: 特殊数

时间限制: 1 Sec   内存限制: 128 MB
提交: 15   解决: 6
[ 提交][ 状态][ 讨论版]

题目描述

    某天,Zyyyyy和Song想要一比智商高低,于是他们找到了河海ACM元老级先行者JetMuffin。JetMuffin给他们出了一道非常有意思的题目,是一道关于“特殊数”的题目

    一个“特殊数”就是出现的频率最少的数字,给出一组整数,你需要输出这组整数中的“特殊数”。注意如果有很多“特殊数”,你需要按顺序输出它们。

输入

第一行是一个整数 T(1 <= T <= 4), 代表数据组数,
每一组数据第一行包括一个整数n (n <= 100000),
第二行包括n个整数ai (0 <= a_i <= 10^9)。

输出

每一组数据都按照升序输出全部“特殊数”。

样例输入

2
7
1 1 2 2 3 3 3
5
5 3 2 4 1

样例输出

1 2
1 2 3 4 5

提示

注意最后一个数后面没有空格。

来源


//E
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<map>
using namespace std;
const int maxn = 100010;
int a[maxn];
int res[maxn];
map<int,int> judge;
int main(){
    int t,n,m,i,j,p;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        judge.clear();
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            judge[a[i]]++;
        }
        int minn = 1000000002;
        //cout<<"tes "<<minn<<endl;
        for(i=1;i<=n;i++){
            minn = min(judge[a[i]],minn);
        }
        j = 0;
        for(i=1;i<=n;i++){
            if(judge[a[i]]==minn){
                res[++j] = a[i];
            }
        }
        sort(res+1,res+1+j);
        for(i=1;i<=j;i++){
            printf("%d",res[i]);
            bool flag = false;
            while(i!=j&&res[i+1]==res[i]){
                i++;
                flag = true;
            }
            if(i!=j){
                printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值