第二场题目更加偏向数学,可惜学算法的时候把高数丢了,第二场罚坐五小时。
比完赛后面去看了三道被称为签到题的题解。下面是这三道题的思路和代码。
Problem G. Limit
Given 2n integers,a1,a2,...,an,b1,b2,...,bn,and an integer t. You need to calculate:
这道题就是计算该公式,搜了下题解基本都是用的泰勒展开,展开公式如下:
代码如下:
#include<iostream>
using namespace std;
const int N = 100005;
int a[N],b[N],g[5];
int main()
{
int n,t;
cin>>n>>t;
if(t == 0)
{
cout<<0;
return 0;
}
for(int i = 1; i <= n; i++)
{
cin>>a[i]>>b[i];
g[0] += a[i] * b[i];
g[1] -= a[i] * b[i] * b[i];
g[2] += a[i] * b[i] * b[i] * b[i];
g[3] -= a[i] * b[i] * b[i] * b[i] * b[i];
g[4] += a[i] * b[i] * b[i] * b[i] * b[i] * b[i];
}
for(int i = 0; i < t - 1; i++)
{
if(g[i])
{
cout<<"infinity";
return 0;
}
}
cout<<g[t - 1] / t;
return 0;
}
Problem J. Leaking Roof
该题大概题意就是有n * n块屋顶,现在有场强降雨,降水量为每块屋顶m的水,且水流会从高处流向低处,若未流动的屋顶块记为0。问最后这n * n块屋顶每块的含水量。
解题思路:从屋顶最高的点向低处遍历,每次判断该屋顶的上下左右四块相邻屋顶能否流水,能流就均等流向相邻低的屋顶。最后输出每个点的最终含水量。
代码如下:
#include<iostream>
#include<algorithm>
#include<iomanip>
#define int long long
using namespace std;
int h[505][505],cnt = 0,n,m;
double s[505][505];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
//结构体存放每个点的坐标和屋顶高度
struct node{
int x,y,h;
//结构体按照屋顶高度逆序排序
bool operator < (const node p){
return h > p.h;
}
}a[300005];
//处理t点的水流
void judge(node t)
{
int sum = 0;
//遍历该点的四个方向能否流水
for(int i = 0; i < 4; i++)
{
int X = t.x + dx[i];
int Y = t.y + dy[i];
//水流能够流向(X,Y)
if(X >= 0 && X < n && Y >= 0 && Y < n && h[t.x][t.y] > h[X][Y])
{
sum++;
}
}
//若该点水流有可流方向
if(sum)
{
//遍历四个方向找出可以流向的点
for(int i = 0; i < 4; i++)
{
int X = t.x + dx[i];
int Y = t.y + dy[i];
//若水流能够流向(X,Y),为(X,Y)增添相应的水
if(X >= 0 && X < n && Y >= 0 && Y < n && h[t.x][t.y] > h[X][Y])
{
s[X][Y] += s[t.x][t.y] / sum;
}
}
}
}
main()
{
cin>>n>>m;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
cin>>h[i][j];
//存入每个点的坐标和高度
a[cnt].x = i;
a[cnt].y = j;
a[cnt++].h = h[i][j];
//为每个点赋初值
s[i][j] = m;
}
}
int max0 = n * n;
//房顶按高到低排序
sort(a,a + max0);
//遍历每个点处理每个点的水流
for(int i = 0; i < max0; i++)
{
judge(a[i]);
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
//该点未漏水,记为0
if(h[i][j] != 0) cout<<0<<" ";
else cout<<fixed<<setprecision(6)<<s[i][j]<<" ";
}
puts("");
}
return 0;
}
Problem M. Addition
该题就是一个二进制运算的升级,除了二进制加法还增添了一个来控制加减法。
解题思路:先对每位进行,然后判断每一位的数字是否合法,若不合法就判断
和
的符号是否相同,相同就计算二进制加法,不同就计算二进制减法。
代码如下:
#include<iostream>
using namespace std;
int main()
{
int n,a[65],b[65],c[65],ans[65];
cin>>n;
for(int i = 0; i < n; i++) cin>>c[i];
for(int i = 0; i < n; i++) cin>>a[i];
for(int i = 0; i < n; i++) cin>>b[i];
for(int i = 0; i < n; i++) ans[i] = a[i] + b[i];
for(int i = 0; i < n; i++)
{
if(ans[i] >= 2)
{
ans[i] -= 2;
int j = i + 1;
if(c[i] == c[j]) ans[j]++;
else
{
if(ans[j] > 0) ans[j]--;
else
{
while(c[i] != c[j])
{
if(ans[j] == 0)
{
ans[j] = 1;
j++;
}
else
{
ans[j]--;
break;
}
}
if(c[i] == c[j]) ans[j]++;
}
}
}
}
cout<<ans[0];
for(int i = 1; i < n; i++) cout<<" "<<ans[i];
return 0;
}
代码源自网络,侵删