一会儿换教室,总结一下
刚刚的任务
6. 学会分治策略
7. 排序算法
a) 归并排序 hdu 1425
b) 快速排序 hdu 1425
c) 计数排序 hdu 1425(不知道这里用hash算不算计数排序。。。总感觉hash是简化版的计数排序。。。好吧我是弱菜。。)
8. 数论
a) 扩展欧几里德算法 hdu 1576 2699
b) 求逆元 ..同上。。。
c) 同余方程 ..为什么看到同余方程我只会想到快速幂。。
d) 中国剩余定理 hdu 1788..(这题真的是中国剩余定理么。。。)
排序是老内容,直接拖我一直在学习的一个人的算法模版,他的好多算法写的真好~
他的主页:http://my.csdn.net/liufeng_king
排序算法多写几遍自然熟能生巧~
对于数论部分的内容。。
唉。。
数学这种东西会了就是会了,不会就是不会...
这种东西只能学知识点搜应用然后记住下一次遇到同类型题套公式。。。
加油吧。。
题解:
hdu 1425:http://acm.hdu.edu.cn/showproblem.php?pid=1425
#include<iostream>
using namespace std;
int a[1000005];
int b[1000005];
void Merge(int c[],int d[],int l,int m,int r)
{
int i=l;
int j=m+1;
int k=l;
while((i<=m)&&(j<=r))
{
if(c[i]<=c[j])
{
d[k++]=c[i++];
}
else
{
d[k++]=c[j++];
}
}
if(i>m)
{
for(int q=j;q<=r;q++)
{
d[k++]=c[q];
}
}
else
{
for(int q=i;q<=m;q++)
{
d[k++]=c[q];
}
}
}
void MergeSort(int a[],int left,int right)
{
if(left<right)
{
int i=(left+right)/2;
MergeSort(a,left,i);
MergeSort(a,i+1,right);
Merge(a,b,left,i,right);
for(int g=left;g<=right;g++)
{
a[g]=b[g];
}
}
}
int Partition(int a[],int p,int r)
{
int i=p;
int j=r+1;
int x=a[p];
while(1)
{
while(a[++i]<x&&i<r)
;
while(a[--j]>x)
;
if(i>=j)
{
break;
}
swap(a[i],a[j]);
}
a[p]=a[j];
a[j]=x;
return j;
}
void QuickSort(int a[],int p,int r)
{
if(p<r)
{
int q=Partition(a,p,r);
QuickSort(a,p,q-1);
QuickSort(a,q+1,r);
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
// QuickSort(a,0,n-1);
MergeSort(a,0,n-1);
for(int i=n-1;i>n-m-1;i--)
{
printf("%d",a[i]);
if(i!=n-m)
{
printf(" ");
}
}
printf("\n");
}
system("pause");
return 0;
}
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define MAXN 1000005
#define N 500000
using namespace std;
bool hash[MAXN];
int main(void)
{
int n,m;
while(cin>>n>>m)
{
memset(hash,0,sizeof(hash));
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
hash[a+N]=true;//数组下标非负
}
int total=0;
for(int i=MAXN;i>=1;i--)
{
if(hash[i]==true)
{
total++;
if(total==m)
{
printf("%d\n",i-N);
break;
}
else printf("%d ",i-N);
}
}
}
system("pause");
}
hdu 1576: http://acm.hdu.edu.cn/showproblem.php?pid=1576
/*
扩展欧几里德算法应用,
这篇题解讲的非常详细之极!!!
http://blog.csdn.net/lulipeng_cpp/article/details/7612490
解决该题的关键是:
1、了解扩展欧几里德算法,可以运用其解出gcd(a,b)=ax1+by1中的x1、y1的值
2、由题可得以下内容:
n=A%9973,则n=A-A/9973*9973。又A/B=x,则A=Bx。所以Bx-A/9973*9973=n。即Bx-9973y=n。
到这里我们可以发现:只要求出x的值,即可算出x%9973,也就是(A/B)%9973了。顺利解决了!
3、题目关键转到如何求出x了。题目的输入是n和B,利用扩展欧几里德算法可求出gcd(B,9973)=Bx1+9973y1=1的x1。
等式两边同乘以n,得B(nx1)-9973(-ny1)=n。可知nx1就是Bx-9973y=n的解了!!!即x=nx1。
4、对于第三部得到的x可能是负数,由题这显然是不正确的。
可以做这样的转化:(x%9973+9973)%9973
*/
#include<iostream>
#define M 9973
using namespace std;
int x,y;
void extendGcd(int a,int b)
{
if(b==0)
{
x=1;
y=0;
return ;
}
else
{
extendGcd(b,a%b);
int temp=x;
x=y;
y=temp-a/b*y;
}
}
int main()
{
int T;
int n,b;
cin>>T;
while(T--)
{
x=y=0;
cin>>n>>b;
extendGcd(b,M);
x=x*n;
int ans=(x%M+M)%M;
cout<<ans<<endl;
}
system("pause");
return 0;
}
hdu 2699: http://acm.hdu.edu.cn/showproblem.php?pid=2699
/*
裸扩展欧几里德
*/
#include<iostream>
using namespace std;
long long x,y,temp,gcd;
int extendGcd(long long a,long long b)
{
if(b==0)
{
x=1;
y=0;
return a;
}
else
{
long long d=extendGcd(b,a%b);
temp=x;
x=y;
y=temp-a/b*y;
return d;
}
}
int main()
{
long long a,b;
while(cin>>a>>b)
{
x=0;
y=0;
temp=0;
gcd=extendGcd(a,b);
if(gcd!=1)
{
cout<<"sorry"<<endl;
}
else
{
while(x<0)
{
x=x+b;
y=y-a;
}
cout<<x<<" "<<y<<endl;
}
}
system("pause");
return 0;
}
hdu 1788: http://acm.hdu.edu.cn/showproblem.php?pid=1788
/*
百度说这题是关于中国剩余定理的?
。。
为什么做了半天感觉就是求n个数的最小公倍数。。
*/
#include<iostream>
using namespace std;
long long gcd(long long a,long long b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int n,m;
while(cin>>n>>m,n!=0&&m!=0)
{
long long ans=1;
long long temp;
for(int i=0;i<n;i++)
{
cin>>temp;
ans=(ans*temp)/gcd(ans,temp);
}
cout<<ans-m<<endl;
}
system("pause");
return 0;
}
终于要开始做博弈题啦~~~话说刚接触编程的时候参加比赛自己只会做简单的博弈题。。。找规律什么的。。。