7-2 a*b
#include<iostream>
using namespace std;
const int N=1200;
string s;
int num1[N],num2[N],ans[2*N];
char print[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
int read(int a[]){
cin>>s;
int n=s.length();
for(int i=0;i<n;i++){
if(s[n-1-i]>='0'&&s[n-1-i]<='9'){
a[i]=s[n-i-1]-'0';
}
else{
a[i]=s[n-i-1]-'A'+10;
}
}
return n;
}
int main(){
int len1=read(num1);
int len2=read(num2);
int len3=2*N-1;
for(int i=0;i<len1;i++){
for(int j=0;j<len2;j++){
ans[i+j]+=num1[i]*num2[j];
}
}
for(int i=0;i<=len3;i++){
if(ans[i]>=16){
ans[i+1]+=ans[i]/16;
ans[i]%=16;
}
}
while(ans[len3]==0&&len3>0)len3--;
for(int i=len3;i>=0;i--){
cout<<print[ans[i]];
}
return 0;
}
十六进制的高精乘,不要把它转成十进制计算,直接在计算中转化一下,逢16进1,然后把10以后的转化为字母就行,但中间有一些细节还是要注意的。
7-3 山头狙击战
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,a[100005];
bool check(int x){
int step = 0;
if(a[1] > m){
step += a[1] - m;
}
for(int i = 2;i <= n; i++){
step += x;
if(a[i] - step < 0) return false;
if(a[i] - step > m) step = a[i] - m;
}
return true;
}
int main()
{
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> a[i];
}
sort(a + 1, a + 1 + n);
int l = -1,r = 1e9;
while(l + 1 != r){
int mid = (l + r) >> 1;
if(!check(mid)) r = mid;
else l = mid;
}
cout << l << endl;
return 0;
}
二分答案和模板一样,主要题意理解,在二分前排序,调用的函数学大佬的思路写的,先大于最近的敌人,然后通过循环一个个比较。
7-4 Reversing Linked List
翻译一下:
给定一个常数K和一个单链表L,你应该反向L上的每K个元素的链接。例如,给定L为1→2→3→4→5→6,如果K=3,那么你必须输出3→2→1→6→5→4;如果K=4,则必须输出4→3→2→1→5→6。
输入规格:
每个输入文件包含一个测试用例。对于每种情况,第一行包含第一个节点的地址,一个正N(≤10的5次方),这是节点的总数,和一个正的K(≤N),这是要反转的子列表的长度。节点地址为5位非负整数,NULL用-1表示。
接下来是N行,每一行描述一个节点,格式如下: Address Data Next
其中Address是节点的位置,Data是一个整数,Next是下一个节点的位置
思路:
用数组模拟(但还没学太会)
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10005;
int temp;
int nt[N],dt[N],lt[N],ans[N];
int main() {
int first, k, n, sum = 0;
cin >> first >> n >> k;
for (int i = 0; i < n; i++) {
cin >> temp;
cin >> dt[temp] >> nt[temp];
}
while (first != -1) {
lt[sum++] = first;
first = nt[first];
}
for (int i = 0; i < sum; i++) ans[i] = lt[i];
for (int i = 0; i < (sum - sum % k); i++)
ans[i] = lt[i / k * k + k - 1 - i % k];
for (int i = 0; i < sum - 1; i++)
printf("%05d %d %05d\n", ans[i], dt[ans[i]], ans[i + 1]);
printf("%05d %d -1", ans[sum - 1], dt[ans[sum - 1]]);
return 0;
}
7-5 一元三次方程
#include<bits/stdc++.h>
using namespace std;
#define lim 1e-6
double a,b,c,d,p,q,T,x1,x2,middle;
double f(double x) {
return a*x*x*x+b*x*x+c*x+d;//简便写法,避免重复写公式
}
double func(double x,double y){
double L=x,R=y;
while(fabs(f(L)-f(R))>=lim)
{
middle=(R+L)/2.0;
if(f(middle)*f(L)<0) R=middle;//零点存在定理
else L=middle;
}
return R;
}
int main(){
cin>>T;
while(T--)//T组数据
{
cin>>a>>b>>c>>d>>p>>q;
x1=(-2.0*b-sqrt(4*b*b-12*a*c))/(6*a);//求导找两个极值点,划分三个区间
x2=(-2.0*b+sqrt(4*b*b-12*a*c))/(6*a);
if(x1>x2) swap(x1,x2);//确保区间顺序
cout<<fixed<<setprecision(6)<<func(p,x1)<<" "<<func(x1,x2)<<" "<<func(x2,q)<<endl;
}
return 0;
}
一元三次方程找零点:题目中给了零点存在定理,先求导找到一元二次方程的零点,再在这两个零点和两边界分出的三个区间上进行二分查找,其中在调用函数时调用了一个求函数值的函数,运用公式+理解题意~定义double类型进行二分找到精确度。