第一题:Redundant Paths - POJ 3177 - Virtual Judge
这是一题有关边双强连通分量的题目,之前并没有学习过也没有了解过,在b站看了视频大致看懂了tarjan算法的运行过程但还是一知半解yyyy
题解如下:
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e5+10;
vector<ll>g[N];
stack<ll>s;
ll n,m;
ll low[N],dfn[N],col[N],times=0,cnt=0,du[N],fa[N];
//dfn[N]用来记录一个顶点第一次被访问时的时间戳
//low[N]用来记录一个顶点不经过它的父节点最高能访问的祖先节点中最早的时间戳
bool inq[N],ma[4000][4000];
void tarjan(ll u){
dfn[u]=low[u]=++times;
s.push(u);
inq[u]=true;
for(int i=0;i<g[u].size();i++){
ll to=g[u][i];
if(!dfn[to]){
fa[to]=u;
tarjan(to);
low[u]=min(low[u],low[to]);
}
else if(to!=fa[u])
low[u]=min(low[u],dfn[to]);
}
if(dfn[u]==low[u]){
cnt++;
ll y;
do{
y=s.top();inq[y]=false;
col[y]=cnt;
s.pop();
}while(y!=u);
}
}
int main()
{
cin>>n>>m;
memset(fa,-1,sizeof(fa));
ll u,v;
for(int i=1;i<=n;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<g[i].size();j++){
if(col[i]!=col[g[i][j]]){
du[col[i]]++;
}
}
}
ll sum=0;
for(int i=1;i<=cnt;i++){
if(du[i]==1){
sum++;
}
}
cout<<(sum+1)/2<<endl;
return 0;
}
第二题:Pseudoprime numbers - POJ 3641 - Virtual Judge
这一题运用到快速幂(参考c++入门必学算法 快速幂_c++快速幂_旧林墨烟的博客-CSDN博客
了解并学习了快速幂)
题解:
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll p,a;
ll kpow(ll a,ll b){//快速幂的板子
ll ans=1;
while(b){
if(b&1){
ans=ans*a%p;
}
b>>=1;
a=a*a%p;
}
return ans%p;
}
bool Prime(ll x){//判断p是不是素数
if(x==2){
return true;
}
for(ll i=2;i<=sqrt(1.0*x);i++){
if(x%i==0){
return false;
}
}
return true;
}
int main()
{
while(cin>>p>>a){
if(p==0&&a==0){
break;
}
if(!Prime(p)&&a==kpow(a,p)){
cout<<"yes"<<endl;
}
else cout<<"no"<<endl;
}
return 0;
}
第三题:P3382 【模板】三分法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
三分跟二分很像,二分适用于单调函数,三分适用于单峰谷函数。首先找出一个mid和取一个极小值eps,mid1=mid-eps,mid2=mid+eps,将区域划分为三段(就是所谓的三分)
题解:
#include <iostream>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const double INF=0x3f3f3f3f;
const double eps=1e-7;
int n;
double l,r;
double a[23];
double f(double x){
double sum=0;
for (int i = 1; i <= n+1; ++i) {//秦九韶算法
sum=sum*x+a[i];
}
return sum;
}
int main(){
cin>>n>>l>>r;
for (int i = 1; i < n+1; ++i) {
cin>>a[i];
}
while(fabs(l-r)>eps){
double mid=(l+r)/2.0;
if (f(mid-eps)<f(mid+eps)) l=mid;
else r=mid;
}
cout<<l<<endl;
return 0;
}
第四题:P1570 KC 喝咖啡 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
纯纯的二分题,根据题意将sigma(v[i])/sigma(w[i])>=mid转换为sigma(v[i]-mid*w[i])>=0
题解:
#include <iostream>
#include <queue>
#include<algorithm>
using namespace std;
const int N=205;
const double INF=0x3f3f3f3f;
const double eps=1e-8;
double v[N],c[N];
int n,m;
double e[N];
bool check(double x){
double sum=0;
for(int i=0;i<n;i++){
e[i]=v[i]-x*c[i];
}
sort(e,e+n);
for (int i = 0; i < m; ++i) {
sum+=e[n-i-1];
}
return sum>=0;
}
void solve(){
double l=0,r=INF,mid;
while(r-l>eps){
mid=(l+r)/2.0;
if (check(mid)) l=mid;
else r=mid;
}
printf("%.3f\n",r);
}
int main(){
cin>>n>>m;
for (int i = 0; i < n ; ++i) {
cin>>v[i];
}
for (int i = 0; i < n; ++i) {
cin>>c[i];
}
solve();
return 0;
}
第五题:P8667 [蓝桥杯 2018 省 B] 递增三元组 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
根据题意以b为中间值进行循环,在c中找到比b大的数的个数cnt,在a中找到比b小的数的个数 cur,Σ(cur*cnt)就是总的组合个数
题解:
#include <iostream>
#include <queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const double INF=0x3f3f3f3f;
const double eps=1e-8;
ll n,ans;
int a[N],b[N],c[N];
ll lena, lenc;
int main(){
cin>>n;
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) {
cin>>c[i];
}
sort(a,a+n);
sort(b,b+n);
sort(c,c+n);
for (int i = 0; i < n; ++i) {
lenc = n-(upper_bound(c,c+n,b[i])-c);
lena = lower_bound(a,a+n,b[i])-a;
ans += lena*lenc;
}
cout<<ans<<endl;
return 0;
}
第六题:P1168 中位数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题解:
#include <iostream>
#include <algorithm>
#include <vector>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int n,x;
vector<int>a;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
cin>>n;
for (int i = 1; i <= n; ++i) {
cin>>x;
//找中位数嘛,那需要排序,通过利用vector的插入函数和upper_bound()
//第一个数直接输出的,每次x插入到数组并排序
a.insert(upper_bound(a.begin(),a.end(),x),x);
//要求输出前奇数个数的中位数
if (i%2==1) cout<<a[(i-1)/2]<<endl;
}
return 0;
}
这一周本新人刚刚来还没有什么大的体会,觉得还挺有趣的吧,虽然我目前还是个小蒟蒻,算法能力还很差,也正说明还有很大的进步空间,接下来好好学吧,争取大的飞跃。