暑假测试一总结

来源:互联网 发布:什么叫网络电视 编辑:程序博客网 时间:2024/06/05 08:04




暑期测试一

 

数学作业

homework.cpp

【问题描述】

求:方程x1+2x2+„+nxn=m的所有非负整数解(x1,x2,„,xn)的个数。例如,方程:x1+2x2+3x3+4x4+5x5=57组解:(5,0,0,0,0)、(3,1,0 ,0,0)、……、(0,0,0,0,1)。

 【输入数据】(homework.in)

2个整数nm

【输出数据】(homework.out)

方程非负整数解的个数ans,如果解超过10^9,只需输出ansmod 10^9

【输入样例】 55

【输出样例】 7

【数据范围】

1≤n≤50000≤m≤5000

 

 

这道题可以将方程中的x1x2.....看作n个有价值的物品,要使这个方程刚好有解,则我们可以联想到完全背包问题中找方案类型的题目。抽象出来则可以描述为:有n件物品,重量依次为1n,要将这些物品放入背包且刚好装满背包,求总方案数。接着粘上标准代码,AC

注意!!!!!!每次状态转移后记得将求解的子问题答案Mod 10^9!!

否则变量爆掉!!

 

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m;long long f[10000];int main(){freopen("homework.in","r",stdin);freopen("homework.out","w",stdout);scanf("%d%d",&n,&m);if(m==0){printf("1");return 0;}f[0]=1;for(int i=1;i<=n;i++)for(int j=i;j<=m;j++)//分配i到m个空间 f[j]=(f[j]+f[j-i])%1000000000;printf("%lld",f[m]);return 0;}

魔法石的诱惑

rob.cpp

问题描述

修罗魔王远远地看见邪狼王狂奔而来,问道:慌慌张张干什么?

邪狼王大口大口初期:我路过一家魔法石店,看到摆着那么多高阶魔法石,我就去抢了一大袋。

修罗王怒道:光天化日之下,朗朗乾坤,众目睽睽之下,你也敢抢?

狼王:我只看到了魔法石,没有看到人。。。

修罗王:。。。。。

其实邪狼王的贪婪也很容易理解,因为高阶魔法石有一个特征,即它的重量进行阶乘运算后末尾有几个0,就拥有同等重量普通魔法石几倍的法力,例如5=5*4*3*2*1=120,所以120有一个0,这意味着该魔法石拥有同等重量的普通魔法石1倍的魔法力,你的任务是找到最小的自然数N,使N!在十进制下有Q0结尾。

 

 

输入格式(rob.in)

一个数Q0≤Q≤10^8

输出格式(rob.out)

如果无解,输出”No solution”,否则输出N

输入样例

2

输出样例

10

 

二分枚举答案,同时算出该数的阶乘所包含的0的个数

如何算阶乘中0的个数:102*5组成,阶乘中2远远大于5,所以只用关注5的个数,注意25 125等数中包含多个5,需要另行判断

枚举答案后还获得最优解,要进行判断处理才得出最优解

 

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int Q;int DuiShu(int n){//取以5为底,n的对数 int pre=1,nxt=5;for(int i=0;i<=20;i++){if(n>=pre&&n<nxt) return i;pre*=5; nxt*=5;}}int calc(int n){//计算n的阶乘有多少个5int ds=DuiShu(n),sum=0;//取对数int pre=5,nxt=25;for(int i=1;i<=ds;i++){//每5^i个数产生一个0sum+=n/pre;pre*=5; nxt*=5;}return sum;} int BinarySearch(int s,int e){//二分查找最佳答案 int mid,ans;while(s<=e){mid=(s+e)/2;ans=calc(mid);if(ans==Q)return mid;else if(ans>Q)//0多了 e=mid-1;else if(ans<Q)//0少了s=mid+1;}return -1;}int FindBest(int ans){if(ans%5!=0)//如果不是最优解ans=ans-(ans%5);return ans;}int main(){freopen("rob.in","r",stdin);freopen("rob.out","w",stdout);scanf("%d",&Q);if(Q==0){printf("1");return 0;}int ans=BinarySearch(5,200000000);if(ans==-1)printf("No solution");elseprintf("%d",FindBest(ans));//printf("%d",DuiShu(30));//测试 return 0;}

 

架设电话线

(phoneline.cpp)

FarmerJohn打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是,FJ必须为此向电信公司支付一定的费用。

   FJ的农场周围分布着N(1<= N <= 1,000)根按1..N顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共P(1< = P <= 10,000)对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接。

   i对电话线杆的两个端点分别为A_iB_i,它们间的距离为L_i(1 <= L_i <= 1,000,000)。数据中保证每对{A_iB_i}最多只出现1次。编号为1的电话线杆已经接入了全国的电话网络,整个农场的电话线全都连到了编号为N的电话线杆上。也就是说,FJ的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。

   经过谈判,电信公司最终同意免费为FJ连结K(0 <= K < N)对由FJ指定的电话线杆。对于此外的那些电话线,FJ需要为它们付的费用,等于其中最长的电话线的长度(每根电话线仅连结一对电话线杆)。如果需要连结的电话线杆不超过K对,那么FJ的总支出为0

请你计算一下,FJ最少需要在电话线上花多少钱。

输入(phoneline.in)

*1: 3个用空格隔开的整数:NP,以及K

*2..P+1:i+1行为3个用空格隔开的整数:A_iB_iL_i

输出(phoneline.out)

*1:输出1个整数,为FJ在这项工程上的最小支出。如果任务不可能完成,输出-1

样例输入

5 7 1 1 2 5 3 1 4 2 4 8 3 2 35 2 9 3 4 7 4 5 6

样例输出

4

 

提示

输入说明:

   一共有5根废弃的电话线杆。电话线杆1不能直接与电话线杆45相连。电话线杆5不能直接与电话线杆13相连。其余所有电话线杆间均可拉电话线。电信公司可以免费为FJ连结一对电话线杆。

输出说明:

   FJ选择如下的连结方案:1->33->22->5,这3对电话线杆间需要的电话线的长度分别为439FJ让电信公司提供那条长度为9的电话线,于是,他所需要购买的电话线的最大长度为4

 

 

这么明显的二分加最短路算法竟然没想到!!!

1.首先二分枚举一个电话线长度标准aim,大于此标准的线交给电信部门,自己支付aim

2.生成带权边,由于要使电信公司刚好支付大于aim的所有线的费用,所以John选择的最佳路线中长度大于aim的电话线数量应该刚好等于K,即大于aim权边为1否则为0,使权和为K即可。权和大于K则表示aim太小,小于K则表示aim太大

3.SPFA最短路径,结合二分法得出答案



0 0
原创粉丝点击