第一周周报

第一题: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;
}

这一周本新人刚刚来还没有什么大的体会,觉得还挺有趣的吧,虽然我目前还是个小蒟蒻,算法能力还很差,也正说明还有很大的进步空间,接下来好好学吧,争取大的飞跃。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值