1.HDU1576 A/B【扩展欧几里得算法+试探法】
Problem Description
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
Input
数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
Output
对应每组数据输出(A/B)%9973。
Sample Input
2 1000 53 87 123456789
Sample Output
7922 6060
Author
xhd
Source
HDU 2007-1 Programming Contest
问题链接:HDU1576 A/B
问题分析:
这个问题有两种解法,一是用扩展欧几里得算法,二是用试探法。似乎后一种方法更快。
解法一:可以用解整数的不定方程来解决,即使用扩展欧几里德算法。
根据题意,输入的n=A%9973(没有输入A),A%B=0(A必能被B整除),B与9973互素(GCD(B,9973)=1)。
解题过程首先是建立方程,然后才能编写程序。
设x=(A/B)%9973(x是最终想计算的值),则9973k+x=A/B(k为整数),得A=9973Bk+xB。
因为n=A%9973与A=9973Bk+xB,所以xB%9973=n,得xB=n+9973y。
故:(x/n)B+(-y/n)9973=1=GCD(B,9973),该方程有解。
要求x和y,先求X=x/n和Y=-y/n,即先解方程BX+9973Y=1。
最后,x=X*n。
需要注意的是,求得的x有可能是负值,需要进行调整。
不过,这个计算方法好像比较花时间。
解法二:试探法
根据题意,输入的n=A%9973(没有输入A),A%B=0(A必能被B整除),B与9973互素(GCD(B,9973)=1)。
解题过程首先是建立方程,然后才能编写程序。
设x=(A/B)%9973(x是最终想计算的值,满足0<=x<=9972),则9973k+x=A/B(k为整数),得A=9973Bk+xB。
因为n=A%9973与A=9973Bk+xB,所以xB%9973=n,得xB=n+9973y,亦得xB-n=9973y。
故:(xB-n)%9973=0
对于上式,只需要用试探法就可以求得x。这样,程序运行速度相当快。
需要主意的是,变量类型为long时没有AC,改为long long就AC了,有点奇怪。也许评价系统所用编译版本的long类型不是64位的,才有这种情况。
扩展欧几里德算法解本问题的方法,时间上则比较慢。试探法有时也是高效率的。
AC的C语言程序如下(解法一):
#include<stdio.h>
long exgcd(long a,long b,long *x,long *y)
{
long x0=1,y0=0,x1=0,y1=1;
long r,q;
*x=0;
*y=1;
r=a%b;
q=(a-r)/b;
while(r)
{
*x=x0-q*x1;
*y=y0-q*y1;
x0=x1;
y0=y1;
x1=*x;
y1=*y;
a=b;
b=r;
r=a%b;
q=(a-r)/b;
}
return b;
}
int main(void)
{
int t,i;
long n,b,a=9973,x,y;
scanf("%d",&t);
for(i-0;i<t;i++){
scanf("%ld%ld",&n,&b);
exgcd(b,a,&x,&y);
x=(x+a)%a;
printf("%ld\n",x*n%a);
}
return 0;
}
AC的C语言程序如下(解法二):
#include<stdio.h>
int main(void)
{
int i,t,j;
long long n,b,a=9973;
scanf("%d",&t);
for(i=0;i<t;i++){
scanf("%lld%lld",&n,&b);
for(j=0;j<a;j++)
if((j*b-n)%a==0){
printf("%d\n",j);
break;
}
}
return 0;
}
2.I00001 杨辉三角
杨辉三角国际上称为Pascal三角形。
杨辉三角与菲波拉契数列也是有关系的,看以下的图就知道了。
这里给出来两种方法的实现,一是使用二维数组来存储杨辉三角,二是使用一维数组来存储杨辉三角并且一边计算一边输出结果。
使用一维数组作为存储,实现打印杨辉三角,需要的技巧更高一些。
#include<stdio.h>
//使用二维数组的杨辉三角
void pascal1()
{
int n,i,j;
scanf("%d",&n);
int pascal[n][n];
for(i=0;i<n;i++)
for(j=0;j<=i;j++){
if(j==0||j==i)
pascal[i][j]=1;
else
pascal[i][j]=pascal[i-1][j]+pascal[i=1][j-1];
}
for(i=0;i<n;i++){
for(j=0;j<=i;j++)
printf("%d",pascal[i][j]);
printf("\n");
}
}
//使用一维数组的杨辉三角
void pascal2()
{
int n,i,j;
scanf("%d",&n);
int pascal[n];
for(i=0;i<n;i++){
for(j=i;j>=0;j--){
if(j==i||j==0)
pascal[j]=1;
else
pascal[j]+=pascal[j-1];
printf("%d",pascal[j]);
}
printf("\n");
}
}
int main(void)
{
pascal1();
pascal2();
return 0;
}
3.KMP算法(C语言版)
有关字符串匹配的最有效的算法。
其算法复杂度为两个字符串的长度之和(m+n)。
#include<stdio.h>
#include<string.h>
void setnext(char t[],int next[])
{
next[0]=-1;
int i;
for(i=1;i<strlen(t);i++){
int j=next[i-1];
while(t[i]!=t[j+1]&&j>=0)
j=next[j];
if(t[i]==t[j+1])
next[i]=j+1;
else
next[i]=0;
}
}
int count_kmp(char s[],char t[],int next[])
{
int t_size=strlen(t);
setnext(t,next);
int index,count=0;
for(index=0;index<strlen(s);++index){
int pos=0;
int iter=index;
while(pos<t_size&&iter<strlen(s)){
if(s[iter]==t[pos]){
++iter;
++pos;
}else{
if(pos==0)
++iter;
else
pos=next[pos-1]+1;
}
if(pos==t_size&&(iter-index)==t_size)
++count;
}
return count;
}
int main(void)
{
char s[]="abaabcacabaabcacabaabcacabaabcacabaabcac";
char t[]="ab";
int next[strlen(t)];
int count=count_kmp(s,t,next);
printf("count=%d\n",count);
return 0;
}
4.KMP算法(C++版)
有关字符串匹配的最有效的算法。
其算法复杂度为两个字符串的长度之和(m+n)。
与C语言版本想比,这个版本只是使用C++语法,功能还是被封装在函数中。
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;
inline void NEXT(const string &T,vector<int> &next)
{
next[0]=-1;
for(int i=1;i<T.size();i++){
int j=next[i-1];
while(T[i]!=T[j+1]&&j>=0)
j=next[j];
if(T[i]==T[j+1])
next[i]=j+1;
else
next[i]=0;
}
}
inline string::size_type COUNT_KMP(const string &s,const string &T)
{
vector<int> next(T.size());
NEXT(T,next);
string::size_type index,count=0;
for(index=0;index<S.size();++index){
int pos=0;
string::size_type iter=index;
while(S[iter]==T[pos]){
++iter;
++pos;
}else{
if(pos==0)
++iter;
else
pos=next[pos-1]+1;
}
}
if(pos==T.size()&&(iter-index)==T.size())
++count;
}
return count;
}
int main(void)
{
string S="abaabcacabaabcacabaabcacabaabcacabaabcac";
string T="ab";
string::size_type count=COUNT_KMP(S,T);
cout<<count<<endl;
return 0;
}