A - Buy a Pen(模拟)
题意:输入红笔r元,绿笔g元,蓝笔b元,不喜欢c笔,求最少花多少钱能买到一支笔
分析:比较除了c笔之外的两根笔,取最小值
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){int r,g,b;cin>>r>>g>>b;string c;cin>>c;if(c[0]=='B')cout<<min(r,g);else if(c[0]=='R')cout<<min(g,b);else cout<<min(r,b);return 0;
}
B - Right Triangle(数学,模拟)
题意:给定三个坐标,求三个坐标俩俩相连围成的三角形是否为直角三角形,如果是输出yes,否则no
分析:先算出每条边,因为第三条边一定大于两边之和,所以再给三条边排序,如果a^2+b^2=c^2就说明是直角三角形
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){int xa,ya,xb,yb,xc,yc;cin>>xa>>ya>>xb>>yb>>xc>>yc;ll a[5];a[1]=(ya-yb)*(ya-yb)+(xa-xb)*(xa-xb);a[2]=(ya-yc)*(ya-yc)+(xa-xc)*(xa-xc);a[3]=(yb-yc)*(yb-yc)+(xb-xc)*(xb-xc);sort(a+1,a+4);if(a[1]+a[2]==a[3])cout<<"Yes"<<endl;else cout<<"No"<<endl;return 0;
}
C - Sum = 0(贪心)
题意:给定n个区间,如果存在x1,x2,...xn(li<=xi<=ri&&∑xi=0)输出yes和序列,否则no
分析:先令所有数字为右区间,如果(最大的数字)小于0,那么永远都不可能变成0,如果(最小的数字)大于0,那么永远都不可能变成0,再从1遍历到n,判断数字是否要向左移动(向左移动了sum就会变小)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){int n;cin>>n;ll l[n+10],r[n+10];int a[n+10];ll sum=0;for(int i=1;i<=n;i++){cin>>l[i]>>r[i];sum+=r[i];}if(sum<0)cout<<"No"<<endl;else{for(int i=1;i<=n;i++){if(sum>r[i]-l[i]){sum-=(r[i]-l[i]);r[i]=l[i];}else if(sum==0)break;else{r[i]-=sum;sum=0;}}if(sum>0){cout<<"No"<<endl;return 0;}cout<<"Yes"<<endl;for(int i=1;i<=n;i++){cout<<r[i]<<" ";}}
}
D - Shortest Path 3(最短路dijkstra)
题意:有n个点和m条边,每个顶点的权重为ai,每条边的边权重bi,找出顶点1到顶点i的路径的最小权重
分析:带夫
代码:
#include <bits/stdc++.h>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
ll n, m, cnt;
ll vis[1000005];
ll dis[1000005];
ll head[1000005];
ll a[1000005];
struct edge
{
ll to; // 点
ll w;
ll next;
} edg[1000005];
struct node
{
ll dis; ll pos;
bool operator<(const node &x) const // 堆优化{
return x.dis < dis;
}
};
void add_edge(ll u, ll v, ll w)
{cnt++;edg[cnt].w = w;edg[cnt].to = v;
edg[cnt].next = head[u];head[u] = cnt;
}
priority_queue<node> q;
void dijkstra()
{node nod;
nod.dis = 0;
nod.pos = 1;
q.push(nod);
while (!q.empty())
{
node tmp = q.top(); // 提取队首元素
q.pop();if (vis[tmp.pos])continue;vis[tmp.pos] = 1;// int W = a[tmp.pos];for (int i = head[tmp.pos]; i; i = edg[i].next){int to = edg[i].to;if (dis[to] > dis[tmp.pos] + edg[i].w + a[to]){
dis[to] = dis[tmp.pos] + edg[i].w + a[to];if (!vis[to])
{
node no;no.dis = dis[to];
no.pos = to;q.push(no);}}}}
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> a[i];
}memset(dis, 0x7f7f7f7f, sizeof(dis)); // 起点到某点的最短路大小memset(vis, 0, sizeof(vis));dis[1] = 0; // 点s到自己的距离0for (int i = 0; i < m; i++)
{int u, v, w;scanf("%d %d %d", &u, &v, &w);add_edge(u, v, w);add_edge(v, u, w);}dis[1] = a[1];dijkstra();for (int i = 2; i <= n; i++)
{
cout << dis[i] << " ";}return 0;
}
E - Count Arithmetic Subsequences(dp)
题意:给定一个数组A,求长度为k的A的子序列中等差数列的个数。模为998244353。如果两个子序列取自不同的位置,即使它们作为序列是相等的,也是有区别的。
分析:设dpi[d]为以i为结尾公差为d的长度为k的个数。k的范围为[1,n]
当len为1时,d为0;当len为2时,d为两数之差
dpi[ai-aj]=(dpj[ai-aj](j的范围为[2,n-1]
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100;
const ll mod=998244353;
ll a[N],ans[N];
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];dp[i][1][0]=1;//长度为1为本身ans[1]++;ans[1]%=mod;for(int j=1;j<i;j++){//长度为2dp[i][2][a[i]-a[j]]++;}ans[2]+=i-1;ans[2]%=mod; }for(int k=3;k<=n;k++){//枚举长度for(int i=3;i<=n;i++){//i为结尾for(int j=i-1;j>=1;j--){//i前面dp[i][k][a[i]-a[j]]+=dp[j][k-1][a[i]-a[j]]%mod;dp[i][k][a[i]-a[j]]%=mod;ans[k]+=dp[j][k-1][a[i]-a[j]]%mod;ans[k]%=mod;}} }for(int i=1;i<=n;i++){cout<<ans[i]<<" ";}cout<<endl;return 0;
}