从零单排1

来源:互联网 发布:文章演技 知乎 编辑:程序博客网 时间:2024/04/29 22:19

在杭电注册了一个新的帐号,从零单排刷OJ搞起

前一段时间好多题目都是直接搜的题解,并没有真正领会要义,这个新号要保证每道题都尽量自己去做,不到万不得已不去搜题解

提纲按照这个链接来,感谢作者:http://blog.csdn.net/niushuai666/article/details/7020773


今天晚上主要做了一些简单数学题,其中

a) 欧几里德算法求最大公约数  1题,主要是上来先练手 hdu 1108
b) 筛法求素数 4题 ,分别是hdu 1164 2098 2136 2138
c) 康托展开 0题,在hdu上木有找到合适的,到一个叫hyoj的上面看了一道,自己写了一份模版
d) 逆康托展开 0题,不过也大概掌握了什么意思
e) 同余定理 1题 hdu 1136
f) 次方求模  2题 hdu 1061 2817

分析过程都写在代码注释里面了,今天主要巩固了筛法求素,学会了康托展开和快速幂求模,有一道快速幂求模也用到了同余定理的知识。

-------------------------------------------------------------------------我是分割线-----------------------------------------------------------------------------------------

hdu 1108:http://acm.hdu.edu.cn/showproblem.php?pid=1108

/*最小公倍数和最大公约数令:int范围为4000000000大一点 1A*/#include<iostream>#include<algorithm>using namespace std;int gcd(int a,int b){int r=a%b;while(r!=0){a=b;b=r;r=a%b;}return b;}int lcm(int a,int b){return a/gcd(a,b)*b;}int main(){int a,b;while(cin>>a>>b){if(a<b)swap(a,b);cout<<lcm(a,b)<<endl;}system("pause");return 0;}
hdu 1164:http://acm.hdu.edu.cn/showproblem.php?pid=1164
/*筛法求素1A*/#include<iostream>#include<cmath>using namespace std;const int N=65535;int a[N];int prime[N];//筛法求素模版void init(){int k=1;memset(a,1,sizeof(a));a[0]=0;a[1]=0;for(int i=2;i<N;i++){if(a[i]){prime[k++]=i;for(int j=i+i;j<N;j+=i){a[j]=0;}}}}void deal(int n){for(int i=1; ;i++){if(n%prime[i]==0){n=n/prime[i];cout<<prime[i];if(n==1){break;}cout<<"*";i--;//继续判断这个素数 continue;}}cout<<endl;}int main(){init();int n;while(cin>>n){deal(n);}system("pause");return 0;}
hdu 2098:http://acm.hdu.edu.cn/showproblem.php?pid=2098
/*还是筛法求素一开始先打表输出了一下不超过10000的素数大约有1230个左右果断hash之,注意hash范围为2N 要注意最后应该将hash[2]置为0这里wa了一次*/#include<iostream>#include<cmath>using namespace std;const int N=10000;int a[N];int prime[N];int hash[2*N];//筛法求素模版void init(){int k=1;memset(a,1,sizeof(a));a[0]=0;a[1]=0;for(int i=2;i<N;i++){if(a[i]){prime[k++]=i;for(int j=i+i;j<N;j+=i){a[j]=0;}}}}void f(){for(int i=1;i<1240;i++){for(int j=i+1;j<=1240;j++){hash[prime[i]+prime[j]]++;}}hash[2]=0;//注意hash[2]=0 }int main(){int n;init();f();while(cin>>n&&n){cout<<hash[n]<<endl;}system("pause");return 0;}
hdu 2136:http://acm.hdu.edu.cn/showproblem.php?pid=2136
/*筛法求素应用开始用cin,cout结果TLE了一开始不知道是这里的错误开大了数组结果MLE了最后改用scanf和print后过了*/#include<iostream>#include<cmath>using namespace std;const int N=1000000;int a[N];//素数表 int lpf[N];//筛法求素模版void init(){int k=0;memset(a,1,sizeof(a));a[0]=0;a[1]=0;lpf[1]=0;for(int i=2;i<N;i++){if(a[i]){k++;lpf[i]=k;for(int j=i+i;j<N;j+=i){a[j]=0;lpf[j]=k;}}}}int main(){int n;init();while(scanf("%d",&n)!=EOF){printf("%d\n",lpf[n]); }system("pause");return 0;}
hdu 2138:http://acm.hdu.edu.cn/showproblem.php?pid=2138
/*本来想套素数表的。。结果果断RE后来该普通方法C++因为sqrt的重载问题过不了G++过了*/#include<iostream>#include<cmath>using namespace std;bool isprime(int n){if(n==1)return false;for(int i=2;i<=sqrt(n);i++){if(n%i==0)return false;}return true;}int main(){int n;while(cin>>n){int a;int sum=0;while(n--){cin>>a;if(isprime(a)){sum++;}}cout<<sum<<endl;}system("pause");return 0;} 
//自己写的模版
/*康托展开木有找到练习题。。先一个模版再说把一个整数X展开成如下形式:X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!其中,a为整数,并且0<=a[i]<i(1<=i<=n){1,2,3,4,...,n}表示1,2,3,...,n的排列如 {1,2,3} 按从小到大排列一共6个。123 132 213 231 312 321 。代表的数字 1 2 3 4 5 6 也就是把10进制数与一个排列对应起来。他们间的对应关系可由康托展开来找到。如我想知道321是{1,2,3}中第几个大的数可以这样考虑 :第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2*2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个。所以321是第6个大的数。 2*2!+1*1!+0*0!就是康托展开。再举个例子:1324是{1,2,3,4}排列数中第几个大的数:第一位是1小于1的数没有,是0个 0*3! 第二位是3小于3的数有1和2,但1已经在第一位了,所以只有一个数2 1*2! 。第三位是2小于2的数是1,但1在第一位,所以有0个数 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2个,1324是第三个大数。*/#include<iostream>#include<cstring>using namespace std;int fac[]={1,1,2,6,24,120,720,5040,40320,362880};int cantor(char s[],int n){int temp,num;num=0;for(int i=0;i<n-1;i++){temp=0;for(int j=i+1;j<n;j++)//n为位数 {if(s[j]<s[i]){temp++;}}num+=fac[n-(i+1)]*temp;}return num+1;} int main(){char s[10];while(cin>>s){cout<<cantor(s,strlen(s))<<endl;}system("pause");return 0;}

hdu 1163:http://acm.hdu.edu.cn/showproblem.php?pid=1163

/*同余定理这题木有什么思路,搜到了题解因为ab*ab=(10*a+b)*(10*a+b)=100*a*a+10*2*a*b+b*b=a*a+2*a*b+b*b=(a+b)*(a+b)abc*abc=(100*a+10*b+c)*(100*a+10*b+c)               =10000*a*a+2000*a*b+100*b*b+200*a*c+20*b*c+c*c               =a*a+2*a*b+b*b+2*a*c+2*b*c+c*c               =(a+b)^2+2*c*(a+b)+c*c              = (a+b+c)*(a+b+c)同理可以知道四位数,五位数也一样,即n*n的数根=n的数根*n的数根数论当中有个结论:“某数乘积的九余数=等于该数九余数的乘积”当余数为0时,该数为九。*/#include <iostream>using namespace std;int main(){int n;while(cin>>n&&n){int i;int s=1;for(i=0;i<n;++i){s=(s*n)%9;}if(s==0)cout<<"9"<<endl;elsecout<<s<<endl;}return 0;} 

hdu 1061:http://acm.hdu.edu.cn/showproblem.php?pid=1061

/*快速幂没有使用long long 导致wa了两次*/#include<iostream>using namespace std;//快速幂模版 int ModExp(long long a,long long b,long n){long long result=1;long long y=a;while(b){if(b%2){result=result*y%n;}y=y*y%n;b/=2;}return result;}int main(){int T;long long num;cin>>T;while(T--){cin>>num;cout<<ModExp(num,num,10)<<endl;}system("pause");return 0;}
hdu 2817:http://acm.hdu.edu.cn/showproblem.php?pid=2817
/*好奇葩的题快速幂然后是学会了用__int64另外long long 导致wa了好多次 */#include<iostream>#include<cstdio>#define N 200907using namespace std;//快速幂模版 __int64 ModExp(__int64 a,__int64 b,__int64 n){__int64 result=1;__int64 y=a;while(b){if(b%2){result=result*y%n;}y=y*y%n;b/=2;}return result;}int main(){    __int64 a,b,c,d,k,q;    scanf("%I64d",&a);    while(a--)    {        scanf("%I64d%I64d%I64d%I64d",&b,&c,&d,&k);        if(2*c==b+d)        {            b=b%N+(k-1)%N*((c-b)%N);            b=b%N;            printf("%I64d\n",b);        }        else if(c*c==b*d)        {            if(k>1)            {                q=(d/c)%N;                b=(b%N)*ModExp(q,k-1,N);                b=b%N;                printf("%I64d\n",b);            }            else            printf("%I64d\n",b);        }    }    return 0;}

明天要把大一上的知识点过完,加油~!

PS:感觉这样很有效果貌似~!

原创粉丝点击