杭电“计算机学院大学生程序设计竞赛(2015’11)”题解【4-6】

1004质方数

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3521 Accepted Submission(s): 1183

Problem Description
小明天生对数字比较敏感,3岁的时候就能背诵圆周率一百位。

现在,小明慢慢长大了,但依然很喜欢数字,最近,他迷上了质数和平方数,并且自己把质数的平方命名为“质方数”。
现在,他在研究这样一个问题:距离一个正整数N最接近的质方数是多少?

Input
输入数据第一行是一个正整数T(T<=20),表示有T组输入数据。
接下来T行,每行输入一个正整数N(1<=N<=10^8)。

Output
对于每组数据,请输出距离N最接近的质方数,每组输出占一行。

Sample Input

2
1
10

Sample Output

4
9

题意概述

寻找距离给定n最近的质方数

题目分析

假设n,m为质数,且n

代码

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

#define Max 10000
int a[Max+1]={1,1,0};

int main(){
    for( int i=2; i<=5000; i++ )
        for( int j=i<<1; j<Max+1; j+=i ){
               a[j]=1;
        }
    int T;
    int N;
    cin>>T;
    while( T-- ){
        cin>>N;
        int temp=sqrt(N);
        if( temp*temp == N && a[temp]==0 )
            cout<<N<<endl;
        else if( temp==1 )
            cout<<4<<endl;
        else{
                int i, j;
                for( i=temp; i>=2; i-- ){
                if( a[i]==0 )
                    break;
            }
            for( j=temp+1; j<=Max; j++ ){
                if( a[j]==0 )
                    break;
            }
            if( N-i*i <= j*j-N )
                cout<<i*i<<endl;
            else
                cout<<j*j<<endl;
        }
    }
}

1005ACM组队安排

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 928 Accepted Submission(s): 437

Problem Description
ACM亚洲区比赛结束,意味着开始备战明年的浙江省大学生程序设计竞赛了!
杭州电子科技大学ACM集训队也准备开始组队。
教练想把所有的n个队员组成若干支队伍,原则是每支队伍至少一人,最多三人。
现在问题来了:如果已知集训队队员的数量n,请你帮教练计算出所有可能的组队方案有多少种。

特别说明:
队伍没有编号,即如果有A,B,C三人,{A}{BC}与{BC}{A}是同一种组队情况。

Input
输入包含多组测试数据(约1000组),每组数据占一行,包含一个数字n(0<=n<=20),表示ACM集训队的队员人数;n为0,表示输入结束。

Output
请输出n个队员所有可能的组队方案数,每组输出占一行。

Sample Input

1
2
3
4
5
0

Sample Output

1
2
5
14
46

题意概述

给定n个人,求出所有组队的可能数(其中可以1人一队,2人一队,也可以3人一队)

题目分析

设d[n]为n个人组队的所有可能数
第m个人的组队方式有以下几种:
1人一队:共有d[m-1]种方式
和其他1人组一队:共有d[m-2]C((n-1),1)=d[m-2]*(n-1)种方式
和其他2人组一队:共有d[m-3]C((n-1),2)=d[m-2](n-1)(n-2)/2
所以d[m]=d[m-1]+d[m-2]*(n-1)+d[m-2]*(n-1)*(n-2)/2

代码

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 1005
int main(){
    int n;
    long long f[N]={0,1,2,5};
    for(int i=4;i<=20;i++){
        f[i]=f[i-1]+(i-1)*f[i-2]+f[i-3]*(i-1)*(i-2)/2;
    }
    while(scanf("%d",&n),n){
        printf("%lld\n",f[n]);
    }
    return 0;
}

1006逆袭指数

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1629 Accepted Submission(s): 314

Problem Description
这依然是关于高富帅小明曾经的故事——

尽管身处逆境,但小明一直没有放弃努力,除了搬砖,小明还研究过东方的八卦以及西方的星座,一直试图在命理上找到自己能够逆袭的依据。

当这些都失败以后,小明转向了数学研究,希望从中得到一些信息。一天,小明在研究《BestCoder逆袭的数理基础》这本书时,发现了宝贵的信息,其中写道:
每个人都存在一个逆袭指数,对于这个逆袭指数,可能存在连续的因子,如果这个连续因子足够长的话,那么这个人逆袭的概率就很大!

小明已知自己的逆袭指数,请告诉小明他最长的连续因子,以让他来判断他自己是否能够逆袭。

Input
输入包含多组测试数据。
每组数据占一行,包含一个整数N,表示小明的逆袭指数,N小于2^31。

Output
对于每组数据,请输出2行:
第一行输出最长的因子个数;
第二行输出最小的因子序列,具体请参考样例。

特别说明:由于小明十分讨厌单身,所以1不算因子。

Sample Input

630
12

Sample Output

3
5*6*7
2
2*3

Hint

630 = 3*5*6*7

题意分析

给定一个数n求n的最长连续因子(1除外)长度(若有多个,取首位最小的那个),且其乘积为n因子。

题目分析

暴力求解
对n所有可能的因子(2..sqrt(n))进行遍历,找出最长的连续因子

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int main()
{
    //cout<<pow(2,2);
    long long  m;
    while(~scanf("%d",&m)){
        long long mult=1;
        long long sum=0;
        long long last = 0;
        long long tempSum = 0;
        long long orig = m;
        for(long long j=2;j*j<=m;j++){
            for(long long i=j;i<=m;i++){
                if(orig%i==0){//是因数
                    mult*=i;
                    if(orig%mult==0){//乘积是因子
                        tempSum++;
                        if(tempSum>sum){//更新
                            sum=tempSum;
                            last = i;
                        }
                    }else{//乘积不是因子 init
                        tempSum = 0;
                        mult = 1;
                        break;
                    }
                }else{//不是因数
                    tempSum = 0;
                    mult = 1;
                    break;
                }
            }
        }
        if(sum==0){
            printf("1\n%d\n",orig);
        }else{
            printf("%d\n",sum);
            for(long long i = sum-1;i>=1;i--){
                printf("%d*",last-i);
            }
            printf("%d\n",last);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值