那些我们仍未知道的数论的小知识

感谢Acdreamer大佬,感谢大佬的博客,这篇博客是弱渣的我将大佬博客中的一些有关的数论小知识总结一下..

默慈金数:

一个给定的数的默慈金数是在一个圆上的个点间,画出彼此不相交弦的全部方法的总数。比如4时,方法数为9,如下图

 

                    


自然数幂合:

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1228

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
typedef long long LL;
const LL MOD = 1000000007;
const int N = 2005;

LL C[N][N];
LL B[N],Inv[N];
LL Tmp[N];
LL n;

void Init()
{
    //预处理组合数
    for(int i=0; i<N; i++)
    {
        C[i][0] = C[i][i] = 1;
        if(i == 0) continue;
        for(int j=1; j<i; j++)
            C[i][j] = (C[i-1][j] % MOD + C[i-1][j-1] % MOD) % MOD;
    }
    //预处理逆元
    Inv[1] = 1;
    for(int i=2; i<N; i++)
        Inv[i] = (MOD - MOD / i) * Inv[MOD % i] % MOD;
    //预处理伯努利数
    B[0] = 1;
    for(int i=1; i<N; i++)
    {
        LL ans = 0;
        if(i == N - 1) break;
        for(int j=0; j<i; j++)
        {
            ans += C[i+1][j] * B[j];
            ans %= MOD;
        }
        ans *= -Inv[i+1];
        ans = (ans % MOD + MOD) % MOD;
        B[i] = ans;
    }
}

LL Work(int k)
{
    LL ans = Inv[k+1];
    LL sum = 0;
    for(int i=1; i<=k+1; i++)
    {
        sum += C[k+1][i] * Tmp[i] % MOD * B[k+1-i] % MOD;
        sum %= MOD;
    }
    ans *= sum;
    ans %= MOD;
    return ans;
}

int main()
{
    int T;
    Init();
    scanf("%d", &T);
    while(T--)
    {
        int k;
        scanf("%I64d %d", &n, &k);
        n %= MOD;
        Tmp[0] = 1;
        for(int i=1; i<N; i++)
            Tmp[i] = Tmp[i-1] * (n + 1) % MOD;
        printf("%I64d\n", Work(k));
    }
    return 0;
}

每一个正整数可以表示为3个三角形数之和

求A(n,m)最后的非零位数字。

#include <iostream>

using namespace std;

int GetCount(int n,int x)    /**计算n!中质因子x出现的次数*/
{
    if(n==0) return 0;
    return n/x+GetCount(n/x,x);
}

int g(int n,int x)           /**计算f(1)到f(n)中奇数数列中末尾为x的数出现的次数*/
{
    if(n==0) return 0;
    return n/10+(n%10>=x)+g(n/5,x);
}

int getx(int n,int x)        /**计算f(1)到f(n)中,末尾为x的数的出现次数*/
{
    if(n==0) return 0;
    return getx(n/2,x)+g(n,x);
}

int table[4][4]=
{
     6,2,4,8,
     1,3,9,7,
     1,7,9,3,
     1,9,1,9
};

int main()
{
    int n,m;
    int num2,num3,num5,num7,num9;
    while(cin>>n>>m)
    {
        num2=GetCount(n,2)-GetCount(n-m,2);
        num5=GetCount(n,5)-GetCount(n-m,5);
        num3=getx(n,3)-getx(n-m,3);
        num7=getx(n,7)-getx(n-m,7);
        num9=getx(n,9)-getx(n-m,9);
        int ans=1;
        if(num5>num2)
        {
            cout<<"5"<<endl;
            continue;
        }
        if(num2!=num5)
        {
            ans*=table[0][(num2-num5)%4];
            ans%=10;
        }
        ans*=table[1][num3%4];
        ans%=10;
        ans*=table[2][num7%4];
        ans%=10;
        ans*=table[3][num9%4];
        ans%=10;
        cout<<ans<<endl;
    }
    return 0;
}

求C(n,m)最后的非零位数字。
#include <iostream>

using namespace std;

int GetCount(int n,int x)    /**计算n!中质因子x出现的次数*/
{
    if(n==0) return 0;
    return n/x+GetCount(n/x,x);
}

int g(int n,int x)           /**计算f(1)到f(n)中奇数数列中末尾为x的数出现的次数*/
{
    if(n==0) return 0;
    return n/10+(n%10>=x)+g(n/5,x);
}

int getx(int n,int x)        /**计算f(1)到f(n)中,末尾为x的数的出现次数*/
{
    if(n==0) return 0;
    return getx(n/2,x)+g(n,x);
}

int table[4][4]=
{
     6,2,4,8,
     1,3,9,7,
     1,7,9,3,
     1,9,1,9
};

int main()
{
    int n,m;
    int num2,num3,num5,num7,num9;
    while(cin>>n>>m)
    {
        num2=GetCount(n,2)-GetCount(n-m,2)-GetCount(m,2);
        num5=GetCount(n,5)-GetCount(n-m,5)-GetCount(m,5);
        num3=getx(n,3)-getx(n-m,3)-getx(m,3);
        num7=getx(n,7)-getx(n-m,7)-getx(m,7);
        num9=getx(n,9)-getx(n-m,9)-getx(m,9);
        int ans=1;
        if(num5>num2)
        {
            cout<<"5"<<endl;
            continue;
        }
        if(num2!=num5)
        {
            ans*=table[0][(num2-num5)%4];
            ans%=10;
        }
        ans*=table[1][(num3%4+4)%4];
        ans%=10;
        ans*=table[2][(num7%4+4)%4];
        ans%=10;
        ans*=table[3][(num9%4+4)%4];
        ans%=10;
        cout<<ans<<endl;
    }
    return 0;
}

高精度求阶乘最后非0位:

#include<stdio.h>
#include<string.h>

#define maxn 10001

const int mod[20]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};

int lastdigit(char buf[])
{
	int len=strlen(buf),a[maxn],i,c,ret=1;
	if(len==1)return mod[buf[0]-'0'];
	for(i=0;i<len;i++)
		a[i]=buf[len-1-i]-'0';
	while(len)
	{
		ret=ret*mod[a[1]%2*10+a[0]]%5;
		for(c=0,i=len-1;i>=0;i--)
		{
			c=c*10+a[i],a[i]=c/5,c%=5;
		}
		len-=!a[len-1];
	}
	return ret+ret%2*5;
}

int main()
{
	char  n[maxn];
	while(scanf("%s",n)!=EOF)
	{
		printf("%d\n",lastdigit(n));
	}
	return 0;
}

给定一个自然数,把它拆分为若干个数的和,记这若干个数的积为,求的最大值。

结论:,使乘积最大的拆分方案是,先拆分出尽多可能的3,如果剩余数为20求N!在K进制下的位数,即计算:,则拆分结束。如果剩余的数为1,则将拆分好的3拿一个和剩余的1组合拆分为两个2 拆结束。

自守数:一个位的自然数,如果它的平方后得到的最后位跟原数相同,那么称自守数

求位数不大于的自守数的个数。

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
typedef long long LL;
const int N = 2005;

int a[N], b[N];
int ans, n;

bool check(int k)
{
    b[k] = 0;
    for(int i = 0; i <= k; i++)
        b[k] += a[i] * a[k-i];
    if(k) b[k] += b[k-1] / 10;
    return b[k] % 10 == a[k];
}

void dfs(int k)
{
    if(k >= n) return;
    for(int i=9; i >= 0; i--)
    {
        a[k] = i;
        if(check(k))
        {
            if(a[k]) ans++;
            dfs(k+1);
        }
    }
}

int main()
{
    while(cin>>n)
    {
        ans = 0;
        dfs(0);
        cout<<ans<<endl;
    }
    return 0;
}

求N!在K进制下的位数,即计算:

解九连环公式:

任何一个大于5的奇数都可以表示为三个素数之和。

,那么有

定理:,那么的值为

     (1)为素数,那么答案就是

     (2)有多个素因子,那么答案就是

     (3)只有一个素因子,那么答案就是该素因子

Fib数,那么有



 



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值