HDU题记

数论

水题集

1108:求两个数的最小公倍数

HDU1108

#include <bits/stdc++.h>
using namespace std;

int gcd(int a,int b){int t;while(b){t=a%b;a=b;b=t;}return a;  }

int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int a,b;//lcm(a,b)=a/gcd(a,b)*b;
    while(cin>>a>>b){
        cout<<a/gcd(a,b)*b<<endl;
    }
    return 0;    
}
板子:gcd(),lcm()

最大公因数lcm(a,b)=a /gcd(a,b) *b :注意顺序防爆


int gcd(int a,int b){int t;while(b){t=a%b;a=b;b=t;}return a;  }
int lcm(int a,int b){return a/gcd(a,b)*b; }
/*
int gcd(int a,int b){
	int t;
	while(b){
		t=a%b;
	    a=b;
	    b=t;
	}
	return a;  
}
*/

2028:多个数的最小公倍数

HDU2028

#include <bits/stdc++.h>
using namespace std;
int a[100000];

int gcd(int a,int b){int t;while(b){t=a%b;a=b;b=t;}return a;  }
int lcm(int a,int b){return a/gcd(a,b)*b; }

int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    while(cin>>n){
        int ans=0;
        cin>>a[0]>>a[1];ans=lcm(a[0],a[1]);
        for(int i=2;i<n;i++){
            cin>>a[i];
            ans=lcm(a[i],ans);
        }
        cout<<ans<<endl;
        memset(a,0,4*n);
    }
    return 0;
}

求a,b,c,d···的最小公倍数:···lcm( lcm( lcm(a,b) , c ) ,d )···

1061:求n的n次方的个位数

HDU 1061
打表:找规律循环节

#include <bits/stdc++.h>
using namespace std;

int a[10][5]={{0},{0},{4,2,4,8,6},{4,3,9,7,1},{2,4,6},{0},{0},{4,7,9,3,1},{4,8,4,2,6},{2,9,1} };
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        if((n%10==0 || n%10==1 ||n%10==5 ||n%10==6)){cout<<n%10<<endl;continue;}
        for(int i=0;i<10;i++){
			if(n%10==i){
				int x=n%a[i][0];
				if(x==0){int y=a[i][0];cout<<a[i][y]<<endl;}
				else cout<<a[i][x]<<endl;
				break;
			}
        }
    }
    return 0;
}

快速幂取余:

#include <bits/stdc++.h>
using namespace std;

int ksm(int a,int n){int ans=1%10;a%=10;while(n){if(n%2)ans=ans*a%10;n/=2;a=a*a%10; }return ans; }

int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        cout<<ksm(n,n)<<endl;
    }
    return 0;
}
板子:快速幂取余
int ksm(int a,int n,int c){int ans=1%c;a%=c;while(n){if(n%2)ans=ans*a%c;n/=2;a=a*a%c; }return ans; }
/*
int ksm(int a,int n,int c){
	int ans=1%c; a%=c;
	while(n){
		if(n%2)ans=ans*a%c;
		n/=2;
		a=a*a%c;
	}
	return ans;    
}
*/

2035: 求A的B次方的最后三位数

HDU2035
快速幂取余

#include <bits/stdc++.h>
using namespace std;

int ksm(int a,int n,int c){int ans=1%c;a%=c;while(n){if(n%2)ans=ans*a%c;n/=2;a=a*a%c; }return ans; }

int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int a,b;
    while(cin>>a>>b){
        if(a==0 &&b==0)break;
        cout<<ksm(a,b,1000)<<endl;
    }
    return 0;
}

1021:新的斐波那契数列(打表题

HDU1021

#include <bits/stdc++.h>
using namespace std;

//1  2  0  2  2  1  0  1
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    while(cin>>n){
        if(n%8==2 || n%8==6)cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }
    return 0;
}

二分/三分

贪心

学习篇

贪心思想
在对问题求解时,总是做出对当前看来是最好的选择。也就是说,不从整体上加以考虑,所做出的仅仅是在某种意义上的局部最优解(全局最优需正明)
若用贪心算法求解某问题的整体最优解,必须首先证明贪心思想在该问题的应用结果就是最优解。
一般 要分清题目是贪心还是dp(能按比例分的一一般是贪心

水题集

2037:求最多看几场球赛(事件序列问题

HDU 2037
想要看最多的,
1、挑时间短的看,很容易举例不成立
2、挑时间开始的早的看,很容易举例不成立
3、挑时间结束的早的看,成立;证明如下
局部最长序列事件:最长事件序列至少有一个是最早结束的事件
反证法证明子问题:最长序列没有最早结束的事件。将最长时间序列中的第一个事件换成最早结束的事件,最长序列还是最长序列事件并且没有冲突,所以局部最长序列事件成立。

//第二次:2.19
#include <bits\stdc++.h>
#define ll long long
using namespace std;


struct node {int s,e;}a[110];
bool cmp(node a,node b){
    if(a.e!=b.e)return a.e<b.e;
    return a.s<b.s;
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n;
    while(cin>>n){
        if(n==0)break;
        for(int i=0;i<n;i++)cin>>a[i].s>>a[i].e;
        sort(a,a+n,cmp);
        int ans=1,x=a[0].e;
        for(int i=0;i<n;i++){
            if(a[i].e!=x&&a[i].s>=x){
                ans++;
                x=a[i].e;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
//第一次:
/*#include <bits/stdc++.h>
#define ll long long

using namespace std;

struct node{int s,e;}a[110];
bool cmp(node a,node b){if(a.e!=b.e)return a.e<b.e;return a.s<b.s; }

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n;
    while(cin>>n){
        if(n==0)break;
        for(int i=0;i<n;i++)cin>>a[i].s>>a[i].e;
        sort(a,a+n,cmp);
        int ans=1,last_end=a[0].e;
        //for(int i=0;i<n;i++)cout<<a[i].s<<a[i].e<<endl;
        for(int i=1;i<n;i++){
            if(a[i].e==last_end)continue;
            if(a[i].s>=last_end){ans++;last_end=a[i].e;}
        }
        cout<<ans<<endl;
    }
    return 0;
}*/

1009:猫鼠换粮食(贪心

HDU 1009
性价比问题

//2.19
#include <bits\stdc++.h>
#define ll long long
using namespace std;

//豆梁 猫粮

struct node {int a,b;double c;}p[1010];
bool cmp(node x,node y){
	if(fabs(x.c-y.c)>1e-6)return x.c>y.c;
}
int main(){
    //ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int m,n;
    while(scanf("%d%d",&m,&n)==2){
		if(n==-1&&m==-1)break;
		for(int i=0;i<n;i++){
			scanf("%d%d",&p[i].a,&p[i].b);
			p[i].c=(double)p[i].a/(double)p[i].b;
		}
		sort(p,p+n,cmp);
		double ans=0.0,t=0.0;
		for(int i=0;i<n;i++){
			if(t+p[i].b<=m){
				ans+=p[i].a;
				t+=p[i].b;
			}
			else {
				ans+=(double)(m-t)*p[i].c;break;
			}
		}
		printf("%.3f\n",ans);
    }
    return 0;
}
/*
#include <bits/stdc++.h>
#define ll long long

using namespace std;

struct node{int x;int y;double z;}a[1100];
bool cmp(node n,node m){if( fabs(n.z-m.z)>0.0001 )return n.z>m.z;}
//性价比z=x/y
int main(){
    int m,n,k;
    while(scanf("%d%d",&m,&n)==2){
        if(m==-1&&n==-1)break;
        for(int i=0;i<n;i++){
            scanf("%d%d",&a[i].x,&a[i].y);
            a[i].z=(double)a[i].x/(double)a[i].y;
        }

        double ans=0;int sum=0;k=m;
        sort(a,a+n,cmp);
        for(int i=0;i<n;i++){
            sum+=a[i].y;
            if(k>=sum){ans+=a[i].x; m-=a[i].y;}
            if(k<sum){
                ans+=a[i].z*m;
                break;
            }
        }
        printf("%.3f\n",ans);
    }
    return 0;
}*/

1050:搬桌子

HDU 1050
要一次搬最多张桌子即这几张桌子不能重叠路线
所以重叠路线最多的次数*10就为至少需要的的时间

#include <bits/stdc++.h>
#define ll long long

using namespace std;

int a[210];
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--){
        int n;cin>>n;int m=0;
        for(int i=1;i<=n;i++){
            int q,p;cin>>q>>p;
            if(q>p){int t=q;q=p;p=t;}
            q=(q+1)/2;p=(p+1)/2+1;
            a[q]++;a[p]--;
            m=max(m,p);
        }
        int ans=-1;
        for(int i=1;i<=m;i++){a[i]+=a[i-1];ans=max(ans,a[i]);}
        cout<<ans*10<<endl;
        for(int i=1;i<=m;i++)a[i]=0;
    }
    return 0;
}

wa了多次

1052:田忌赛马

看了别人的分析才做出来

#include <bits/stdc++.h>
#define ll long long

using namespace std;
int a[1010],b[1010],v[1010];

bool cmp(int a,int b){return a>b;}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n;
    while(cin>>n){
        if(n==0)break;
        for(int i=0;i<n;i++)cin>>a[i];
        for(int i=0;i<n;i++)cin>>b[i];
        sort(b,b+n,cmp);
        sort(a,a+n,cmp);

        int ans=0,i=0,j=0,i2=n-1,j2=n-1;
        while(i<=i2 &&j<=j2){
            if(a[i]>b[j]){i++;j++;ans++; }
            else if(a[i]<b[j]){i2--;j++;ans--; }
            else{
                if(a[i2]>b[j2]){j2--;i2--;ans++; }
                else if(a[i2]<b[j2]){i2--;j++;ans--; }
                else{
                    if(a[i2]<b[j])ans--;
                    i2--;j++;
                }
            }
        }
        cout<<ans*200<<endl;

    }
    return 0;
}

查并集

递推系列

水题集

2454:可图形判定

可图形判定

HDU 2454

#include <bits/stdc++.h>
#define ll long long

using namespace std;

int a[1010];
bool cmp(int a,int b){return a>b;}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        for(int i=0;i<n;i++)cin>>a[i];

        sort(a,a+n,cmp);
        bool k=0;
        while(a[0]){
            int num=a[0],f=0;
            a[0]=0;
            for(int i=1;i<=num;i++){
                a[i]--;
                if(a[i]<0){f=1;break;}
            }
            if(f){k=1;break;}
            sort(a,a+n,cmp);
        }
        if(k)cout<<"no"<<endl;
        else cout<<"yes"<<endl;
        
        for(int i=0;i<n;i++)a[i]=0;
    }
    return 0;
}

简单DP

背包简单问题

最短路问题

BFS/DFS

二分匹配算法

简单组合博弈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值