(未更新完,见一道往文章里添一道)一些算法基本不相同但是都是多项式的一些问题(二次函数或者多项式),不知道怎么归类就先把他们都塞到这篇文章里面吧
A Function
题目来源于2019CCPC女生赛的C题,感觉是很不错的一个题
输入
输入有多行,第一行两个正整数n , m如题意描述
下面有n行每行有三个整数a,b,c分别代表二次函数的二次项,一次项,常数项系数
输出
输出只有一行答案
Sample Input
2 3
1 1 1
2 2 2
Sample Output
13
数据范围
1<=n <= m <=1e5
1 <= a <= 1000
-1000 <= b,c <=1000
(搬运一个很好的思路+代码,本人暂时写不出比这个更好的代码就直接搬运了)
原链接:
思路:由于a大于0,所有二次函数均是开口向上,而且x必须正整数。所以很自然想到先全部分配1.
然后逐个分配,由于二次函数f[i]-f[i-1]左边一定比右边更优,即i越小结果越小。
所以我们可以直接把F[I]-F[I-1]丢到优先队列里。每次让某一个二次函数的x+1,根据前面的分析,一定是队列首的二次函数加1 更优,因为队列里的所有数,将来只可能更大,不会变小。
然后把F[I+1]-F[I]丢回去即可。
(m-n的原因是因为x为正整数,每个数至少要取1,然后剩下的就用优先队列存储就好,说实话我确实是不太会写优先队列套struct,此题也当学习这种写法了)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e5+7;
struct node
{
ll f,x,id;
bool operator <(const node &r)const
{
return f>r.f;
}
}p;
priority_queue<node>q;//逆序规则,变成小根堆
int a[M],b[M],c[M];
ll s(int k,int x)
{
return 1LL*a[k]*x*x+1LL*b[k]*x+c[k];
}
int main()
{
int n,m;
cin>>n>>m;
ll ans=0;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i]>>c[i],ans+=s(i,1),q.push(node{s(i,2)-s(i,1),2,i});
m-=n;
while(m)
{
node tp=q.top();q.pop();
ans+=tp.f;
q.push(node{s(tp.id,tp.x+1)-s(tp.id,tp.x),tp.x+1,tp.id});
m--;
}
cout<<ans<<endl;
return 0;
}
B 二次函数
题目来源于百❀2022新生赛K
题目描述:
给三个点的横纵坐标,确定唯一的二次函数表达式,给第四个点的横坐标求对应的纵坐标
数据范围:
输入
共四行,第一行x1 y1,第二行x2 y2,第三行x3 y3,第四行x4
输出
输出y4(保证输出的一定是整数)
Sample Input
0 1
-1 4
2 1
3
Sample Output
4
(补题抄题解,教练两行泪?思路和算法大概都懂了但是并不是很会写,就先当板子存着?)
#include <stdio.h>
int main(){
double x1, y1, x2, y2, x3, y3, x4;
scanf("%lf%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3, &x4);
double k21 = (y2 - y1) / (x2 - x1), k31 = (y3 - y1) / (x3 - x1);
double kk23 = (k21 - k31) / (x2 - x3);
double k41 = (k21 - ((x2 - x4) * kk23));
double y4 = (k41 * (x4 - x1)) + y1;
printf("%.0lf", y4);
return 0;
}
#include <stdio.h>
#include <math.h>
double x[5], y[5], A[5][5];
int n;
void Gauss() {
for(int i = 0, r; i < n; i ++) {
r = i;
for(int j = i + 1; j < n; j ++)
if(fabs(A[j][i]) > fabs(A[r][i])) r = j;
if(r != i)
for(int j = 0; j <= n; j ++) {
double tmp = A[r][j];
A[r][j] = A[i][j];
A[i][j] = tmp;
}
for(int j = n; j >= i; j --) {
for(int k = i + 1; k < n; k ++)
A[k][j] -= A[k][i] / A[i][i] * A[i][j];
}
}
for(int i = n - 1; i >= 0; i --) {
for(int j = i + 1; j < n; j ++)
A[i][n] -= A[j][n] * A[i][j];
A[i][n] /= A[i][i];
}
}
signed main(){
n = 3;
for (int i = 0; i < n; i++){
scanf("%lf%lf", &x[i], &y[i]);
A[i][0] = x[i] * x[i];
A[i][1] = x[i];
A[i][2] = 1;
A[i][3] = y[i];
}
Gauss();
scanf("%lf", &x[3]);
y[4] = A[0][3] * x[3] * x[3] + A[1][3] * x[3] + A[2][3];
printf("%.0lf\n", y[4]);
return 0;
}
#include <stdio.h>
int main(){
double x[5], y[5];
for (int i = 0; i < 3; i++)
scanf("%lf%lf", &x[i], &y[i]);
scanf("%lf", &x[3]);
double VA[3][3] = {
{x[1] * x[2] * (x[2] - x[1]), x[1] * x[1] - x[2] * x[2], x[2] - x[1]},
{x[0] * x[2] * (x[0] - x[2]), x[2] * x[2] - x[0] * x[0], x[0] - x[2]},
{x[0] * x[1] * (x[1] - x[0]), x[0] * x[0] - x[1] * x[1], x[1] - x[0]}
};
double detV = (x[1] - x[0]) * (x[2] - x[0]) * (x[2] - x[1]);
double a[4] = {0, 0, 0, 0};
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++)
a[i] += VA[j][i] * y[j] / detV;
}
y[3] = a[2] * x[3] * x[3] + a[1] * x[3] + a[0];
printf("%.0lf", y[3]);
return 0;
}
#include <stdio.h>
int main(){
double x[5], y[5];
for (int i = 1; i <= 3; i++)
scanf("%lf%lf", &x[i], &y[i]);
scanf("%lf", &x[4]);
y[4] = ((x[4] - x[1]) * (x[4] - x[2] ) / (x[3] - x[1]) / (x[3] - x[2])) * y[3] +
((x[4] - x[1]) * (x[4] - x[3] ) / (x[2] - x[1]) / (x[2] - x[3])) * y[2] +
((x[4] - x[3]) * (x[4] - x[2] ) / (x[1] - x[3]) / (x[1] - x[2])) * y[1] ;
printf("%.0lf", y[4]);
return 0;
}
#include <stdio.h>
double x[5], y[5];
int n;
double Lagrange(double k){
double res = 0, l;
for (int i = 0; i < n; ++i){
l = 1;
for (int j = 0; j < n; ++j){
if (i == j) continue;
l = l * (k - x[j]) / (x[i] - x[j]);
}
res = (res + l * y[i]);
}
return res;
}
signed main(){
n = 3;
for (int i = 0; i < n; i++)
scanf("%lf%lf", &x[i], &y[i]);
scanf("%lf", &x[3]);
printf("%.0lf\n", Lagrange(x[3]));
return 0;
}
#include <stdio.h>
double x[5], y[5], l[5][5], g[5];
int n;
double Newton(double k){
double res = 0;
for (int i = 0; i < n; i++)
l[i][0] = y[i];
for (int j = 1; j < n; j++){
for (int i = j; i < n; i++){
l[i][j] = (l[i][j - 1] - l[i - 1][j - 1]) / (x[i] - x[i - j]);
}
}
for (int i = 0; i < n; i++) g[i] = 1;
for (int i = 0; i < n; i++){
for (int j = 0; j < i; j++){
g[i] *= (k - x[j]);
}
res += g[i] * l[i][i];
}
return res;
}
signed main(){
n = 3;
for (int i = 0; i < n; i++)
scanf("%lf%lf", &x[i], &y[i]);
scanf("%lf", &x[3]);
printf("%.0lf\n", Newton(x[3]));
return 0;
}
C Complete the Sequence
懒得把题再抄一次了,就在差分那篇(其实和拉格朗日插值法有点关系)