2017.9.20 模拟考试

45 篇文章 0 订阅
37 篇文章 0 订阅

刚来东校第一天就赶上考试,还是聂老大出题….

A 约数之和(count.pas/c/cpp)

TL:1S ML:128MB
【Description】
我们用 D(x)表示正整数 x 的约数的个数。给定一个正整数 N,求 D(1)+D(2)+…+D(N)。
【Input】
一行一个正整数 N。
【Output】
一行一个整数,表示答案
【Sample Input】
5
【Sample Output】
10
【Hint】
样例解释:
D(1)=1 D(2)=2
D(3)=2 D(4)=3 D(5)=2
对于 20%的测试数据:N<=1000
对于 50%的测试数据:N<=100000
对于 100%的测试数据:N<=10000000

//拒绝解释
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n;
inline void read(int &x){
    x=0; int f=1; char c=getchar();
    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;
}
#define LL long long
int Main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    read(n);
    LL ans=0;
    for(int i=1;i<=n;++i)
        ans+=(n/i);
    printf("%I64d\n",ans);
    fclose(stdin);fclose(stdout);
    return 0;
}
int Aptal_is_My_Son=Main();
int main(int argc,char *argv[]){ ; }

B 邮局选址(post.pas/c/cpp)(POJ1160 原题)

TL:1S ML:128MB
【Description】
在 J 市的一条笔直的公路旁分布着 n 个村庄,每个村庄都有一个唯一的坐标 Xi,任意一
对村庄的坐标不同。最近,J 市领导计划在村庄里新建 m 个邮局,而邮局在 n 个村庄里
的分布情况会影响到居民的便利程度。
设 m 个邮局分别建在 P1,P2,..,Pm 号村庄。每个村庄的村民都会找到与其距离最近的一
个邮局, 若有多个距离最近的则会任选一个, 该村庄的便利度即为该村庄与其最近的邮局的
距离,而所有村庄的便利度的和即为总便利度。
严格地讲,总便利度 C 定义为
这里写图片描述
现在,由你来安排邮局的建设位置。请计算最小的 C 是多少。
【Input】
第一行两个整数 n m
第二行递增的 n 个整数,表示 X1..Xn
【Output】
一行一个整数,表示最小的 C
【Sample Input】
10 5
1 2 3 6 7 9 11 22 44 50
【Sample Output】
9
【Hint】
样例解释:建立在坐标为:2 7 22 44 50 的位置
每个村庄的便利度分别为:1 0 1 1 0 2 4 0 0 0
对于 30%的测试数据 n ≤ 10
对于 60%的测试数据 n ≤ 50
对于 100%的测试数据 1 ≤ n ≤ 300; 1 ≤ m ≤ 30; m ≤ n; 1 ≤ Xi ≤ 10000
好不容易会做个DP,王海狗这孙子搜着了题解,我的DP只能90分得,活活把我这老人得rank挤下五个来。

//先贴我的代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
#define MAXN 305
int a[MAXN],n,m,sumb[MAXN],suma[MAXN];
inline void read(int &x){
    x=0; int f=1; char c=getchar();
    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;
}
int f[MAXN][35];
//f[i][j]表示到第i个村庄 共安装了j个邮局的最小的C 且第j个邮局在第i个村庄 
int Main(){
    freopen("post.in","r",stdin);
    freopen("post.out","w",stdout);
    read(n),read(m);
    register int i,j;
    for(i=1;i<=n;++i) read(a[i]);
    memset(f,127/3,sizeof f );
    int Ans=f[0][0];
    for(i=1;i<=n;++i) suma[i]=suma[i-1]+a[i];
    for(i=n;i>=1;--i) sumb[i]=sumb[i+1]+a[i];
    for(i=1;i<=n;++i) f[i][1]=((i-1)*a[i])-suma[i-1]+sumb[i+1]-((n-i)*a[i]);

    for(i=1;i<=n;++i)
        for(j=2;j<=m;++j)
            if(i>=j){
                for(int k=j-1;k<i;++k){
                    int kp=0;
                    for(int l=k+1;l<i;++l)
                        kp+=min(abs(a[i]-a[l]),abs(a[l]-a[k]));
                    f[i][j]=min(f[i][j],f[k][j-1]-(n-i)*a[i]+sumb[i+1]+(n-k)*a[k]-sumb[k+1]+kp);
                }
            }
    for(i=m;i<=n;++i) Ans=min(Ans,f[i][m]);//因为我们的定义。。。 
    printf("%d\n",Ans);
    fclose(stdin);fclose(stdout);
    return 0;
}
int Aptal_is_My_Son=Main();
int main(int argc,char *argv[]){ ; }
//正解
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 305
inline void read(int &x){
    x=0; int f=1; char c=getchar();
    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); }  x*=f;
}
int dp[MAXN][MAXN],minx[MAXN][MAXN],a[MAXN];
int main(){
    freopen("post.in","r",stdin);
    freopen("post.out","w",stdout);
    int n,m;
    read(n),read(m);
    register int i,j;
    for(i=1;i<=n;++i) read(a[i]);
    for(i=1;i<=n;++i)
        for(j=i+1;j<=n;++j)
            minx[i][j]=minx[i][j-1]+a[j]-a[i+j>>1];
    memset(dp,127/3,sizeof dp );
    for(i=1;i<=n;++i)
        dp[i][1]=minx[1][i],dp[i][i]=0;
    for(int k=2;k<=m;++k)
        for(i=1;i<=n;++i)
            for(j=i-1;j;--j)
                dp[i][k]=min(dp[i][k],dp[j][k-1]+minx[j+1][i]);

    printf("%d\n",dp[n][m]);
    fclose(stdin);fclose(stdout);
    return 0;
}

sum[i][j]表示从第i个村庄到第j个村庄只有一个邮局的距离总数;
dp[i][j]表示从第1个村庄到第j个村庄有i个邮局的距离总数;
按照上述思路,就有了下面的状态转移方程:
dp[i][j]=min(dp[i][j],dp[i-1][k]+sum[k+1][j]);
现在的问题就是如何求sum[i][j]了。
显然,只有一个邮局的情况下,在i到j的中点建立距离和是最短的。所以可得:
sum[i][j]=sum[i][j-1]+d[j]-d[(i+j)/2];
d[i]表示第i个村庄的位置。

C 分数(fraction.pas/c/cpp)
TL:2S ML:128MB
【Description】
在一门叫做计算机应用数学的神奇的课上,老师教给大家如何处理小数的进制转换:
p 进制的小数 abc.def 的十进制值为:
这里写图片描述
例如十进制数 1/3 在十进制下小数表示为 0.33333…, 在三进制下为 0.1, 在三十进制下为 0.A。
(这里 A 的含义与十六进制中 A 的含义相同,均表示 10) 。
下课后,老师要求 kAc 将 N 个十进制的分数写成 k 进制下的小数。然而 kAc 发现,很多十进制分数根本不可能写成有限的 k 进制小数!这令他十分不爽,不过他想知道,最小需要几
进制才能使得这些十进制分数在该进制下均为有限的小数。
【Input】
第一行两个整数 N
接下来 N 行,每行两个整数 a, b,表示一个十进制小数 a
b 。
【Output】
一个整数,表示最小进制数。这里,请按照十六进制输出,所有字母全部大写。 (例如,如
果答案为十进制下 26,则输出 1A) 。
【Sample Input】
2
3 99
1 99
1 11
【Sample Output】
21
【Hint】
样例解释:
在 33 进制下,
3
99 可以表示为 0.1,
1
99 可以表示为 0.0B,
1
11 可以表示为 0.3。
可以证明不存在更小的进制,使得他们均为有限小数。
对于 20%的测试数据:n=1
对于 50%的测试数据: n<=10, a, b <= 10000, 保证最终答案在十进制下不超过 10000。
对于 70%的测试数据:n<=100,a, b<= 10000。
对于 100%的测试数据:n<=1000,1 <= a,b <= 1000000000。

管他有事没事的,先贴段子
天王盖地虎
钱(Qan)哥一米五
宝塔镇河妖
钱(Qan)哥到我腰

//70分做法
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
#define LL long long

#define MAXN 3005
LL a[MAXN],b[MAXN];
char s[MAXN];
int n,st;
inline void read(LL &x){
    x=0; int f=1; char c=getchar();
    while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
    while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;
}

inline LL LCM(LL x,LL y){
    return x*y/ __gcd(x,y);
}
bool vis[10000005];
#define INF 10000000
map<int,int> mp;
struct Data{
    int len,a[200001];
    Data(){
        len=1,a[1]=1;
    }
    Data operator * (const int &val ) const {
        Data ret;ret.len=len;
        int tmp=0;
        for(int i=1;i<=ret.len;++i){
            tmp+=a[i]*val;
            ret.a[i]=tmp%16;
            tmp/=16;
        }
        while(tmp) ret.a[++ret.len]=tmp%16,tmp/=16;
        return ret;
    }
    void Print(){
        for(int i=len;i>=1;--i)
            if(a[i]>=0&&a[i]<=9) putchar(a[i]+'0');
            else putchar(a[i]+'A'-10);
    }
}Ans;

int main(){
    freopen("fraction.in","r",stdin);
    freopen("fraction.out","w",stdout);
    scanf("%d",&n);
    LL up,down,tmp;
    for(int i=1;i<=n;++i){
        cin>>up>>down;
        tmp= __gcd(up,down);
        down/=tmp;
        for(int v=2;v<=sqrt(down)&&down>1;++v){
            if(down%v==0){
                if(v>INF){
                    ++mp[v];
                    if(mp[v]==1) Ans=Ans*v;
                    while(down%v==0) down/=v;
                }
                else {
                    if(!vis[v]) vis[v]=true,Ans=Ans*v;
                    while(down%v==0) down/=v;
                }
            }
        }
        if(down>1){
            if(down>INF){
                ++mp[down];
                if(mp[down]==1) Ans=Ans*(int)down;
            }
            else if(!vis[down]) vis[down]=true,Ans=Ans*(int)down;
        }
    }


    Ans.Print();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值