总结二

来源:互联网 发布:手机下载在线视频软件 编辑:程序博客网 时间:2024/06/06 00:57
                   2017.11.6——2017.11.12

周一做的总结,都忘了上一周经历了什么,大概就是双十一吧= =;

本周在51nod上做了很多题。
先来
1.N的阶乘
这是一个大数的阶乘,很有意思。
其实思路很简单,就是将最后的结果分段保存,然后输出。

#include <stdio.h>#define _MAX 100000000int main(){    int n, i, j, m;    long long a[10000], c;    scanf("%d",&n);    m = 0;    a[0] = 1;    for(i = 1; i <= n; i++)    {        c = 0;        for(j = 0; j <= m; j++) //每一个结果片段都要相乘        {            a[j] = a[j] * i + c;            c = a[j] / _MAX;            a[j] %= _MAX;        }        if(c > 0)        {            m++;            a[m] = c;        }    }    printf("%lld", a[m]);    for(i = m - 1; i >= 0; i--)        printf("%0.8lld", a[i]);    printf("\n");    return 0;}

2.N阶乘的长度
这道题就是数学,贴一个公式出来(Stirling公式)。
这里写图片描述

#include <cstdio>#include <math.h>#define pi 3.1415926#define e 2.71828182845int main(){    long long n,res;    scanf("%lld",&n);    res=(log10(2*pi*n)*0.5+n*log10(n/e))+1;  //注意向下取整后加1    printf("%lld",res);}

3.逆序数
这个题用了分治的思想,虽然我还不太会。
本题用的是收录的比较好的方法。(有一种方法是在MSort里面不停开数组进行存储排好序的数字,这样递归次数太多容易爆点)开a,b两个数组,注意因为开了两个一模一样的数组,在分割的时候是来回反着调用(即注意a、b数组的调用)。

#include <stdio.h>#define maxn 50010long ans=0;void Merge(long *a,long *b,int first,int mid,int last){    int i=first,j=mid+1;    int cur=first;    while(i<=mid && j<=last)    {        printf("");  //之前不要这个就会RE 不知道为什么        if(a[i]<=a[j])        {            b[cur++]=a[i++];        }        else        {            b[cur++]=a[j++];            ans+=mid-i+1;        }    }    while(i<=mid)    {        b[cur++]=a[i++];    }    while(j<=last)    {        b[cur++]=a[j++];    }}void MSort(long *a,long *b,int first,int last){    int mid;    if(first<last)    {        mid=(first+last)/2;        MSort(b,a,first,mid);        MSort(b,a,mid+1,last);        Merge(a,b,first,mid,last);    }}int main(){    int N,i=1;    long a[maxn];    long b[maxn];    scanf("%d",&N);    for(;i<=N;i++)    {        scanf("%ld",&a[i]);        b[i]=a[i];    }    MSort(a,b,1,N);    printf("%ld\n",ans);    return 0;}

4.gcd和lcm
gcd

#include<cstdio>long long gcd(long long a,long long b){    if(a==b || b==0)    {        return a;    }    else return gcd(b,a%b);}int main(){    long long a,b;    scanf("%lld %lld",&a,&b);    printf("%lld",gcd(a,b));}

lcm

#include <cstdio>long long gcd(long long a,long long b){    long long temp=a<b?a:b; //注意    while(a%b!=0)    {        temp=a%b;        a=b;        b=temp;    }    return temp;}int main(){    long long a,b;    scanf("%lld %lld",&a,&b);    printf("%lld",a*b/gcd(a,b));    return 0;}

虽然我写的不是很简单,但是毕竟很基本,可以看一看,还是有坑点的。

5.最长公共子序列
题目要求找到两个字符串的最长公共子序列(不要求子序列连续)
//这种题的思想一直不是很会(动态规划??)

#include <cstdio>#include <cstring>#include <algorithm>int cata[1050][1050];char a[1050],b[1050],str[1050];int lena,lenb;int maxn(int a,int b){    return a>b?a:b;}int main(void){    memset(cata,0,sizeof(a));    scanf("%s %s",a,b);    lena=strlen(a);    lenb=strlen(b);    for(int i=1;i<=lena;i++)    {        for(int j=1;j<=lenb;j++)        {            if(a[i-1]==b[j-1])            {                cata[i][j]=cata[i-1][j-1]+1;            }            else            {                cata[i][j]=maxn(cata[i-1][j],cata[i][j-1]);            }        }    }     int k=1050;    int i=lena,j=lenb;    while(i&&j)    {        if(a[i-1]==b[j-1])        {            str[k]=a[i-1];            i--;            j--;            k--;        }        else        {            if(cata[i-1][j]<=cata[i][j-1])            {                j--;            }            else            {                i--;            }        }    }/*    for(int m=0;m<lena;m++)    {        for(int n=0;n<lenb;n++)        {            printf("%d ",cata[m][n]);        }        printf("\n");    }*/    //str[k]='\0';    //strrev(str);    printf("%s",str+k+1);}

6.大数的加减乘法

很有意思,看到了很多很强的方法,有时间另开一个随手。

!!
7.A^B Mod C
这道题最有意思的点就是用到了快速乘法(与矩阵的快速幂,斐波拉契用矩阵来求解一样有意思)

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>long long ans[10000];long long length;int findregu(long long a,long long b,long long c){    int t=1;    a=a%c;    while(b>0)    {        if(b%2==1) t=t*a%c;        a=a*a%c;        b=b/2;    }    return t;}int main(){    long long a,b,c;    scanf("%lld %lld %lld",&a,&b,&c);    printf("%d",findregu(a,b,c));}

//嗯 好像没用到
乘法快速幂的思想就是把指数化为二进制,二进制从小到大前推,同时a自乘得到temp,每遇到1就把temp与ans相乘存在ans,推完即结束。

原创粉丝点击