总结二

                   2017.11.6——2017.11.12

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

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

#include <stdio.h>
#define _MAX 100000000
int 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.71828182845

int 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 50010
long 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,推完即结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值