目录
数论
水题集
1108:求两个数的最小公倍数
#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:多个数的最小公倍数
#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:新的斐波那契数列(打表题
#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:可图形判定
#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;
}