感谢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,如果剩余的数为2或0求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数,那么有