- 计算n的阶乘结果末尾有几个零
int findzero(int x)
{
int ans=0;
while(n>=4) //while(ans)
{
ans+=n/5;
n/=5;
}
return ans;
}
- 组合数与杨辉三角
(1)组合恒等式:C(n,m)=C(n-1,m-1)+C(n-1,m)
(2)杨辉三角形的第i行第j列就是c(i-1,j-1)
(3)c[0][0]=c[1][0]=c[1][1]=1;
(4)求c(m,n):
long long c[105][105];
const int mod = 1000000007;
void init()
{
c[0][0]=1;
for(int i=1;i<=100;i++){
c[i][0]=1;
for(int j=1;j<=100;j++){
c[i][j] = (c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
- 欧拉函数
(1)质因数分解法
int oula[100010];
ll Oular(ll n)
{
ll ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans=ans*i/i-1;
while(n%i==0)
n/=i;
}
}
if(n!=1)
ans=ans*n/n-1;
return ans;
}
(2)线性打表法
const int n=100010;
int oula[n];
void Oula()
{
for(int i=0;i<n;i++)
oula[i]=i;
for(int i=2;i<n;i++)
{
if(oula[i]==i)
{
for(int j=i;j<n;j+=i)
oula[j]=oula[j]/i*(i-1);
}
}
}
- 求n的阶乘的位数
(1)斯特林公式(求n!的近似值):(根号下2PIn)*((n/e)的n次方)
对等号两边同时取以10为底的对数,求出来的位数少一位,例如log10(10)=1,但10是两位数。
斯特林数判断阶乘位数
#include<stdio.h>
#include<math.h>
using namespace std;
#define pi 3.14159265
#define e 2.71828182
int main()
{
int n, digit;
scanf ("%d", &n);
digit= (int) ((0.5 * log (2 * pi * n) + n * log (n) - n * log(e) / log (10));
printf ("%d\n", digit + 1);
return 0;
}
//斯特林数判断阶乘位数
(2)直接log10
任意一个正整数a的位数
等于(int)log10(a) + 1;为什么呢?下面给大家推导一下:
对于任意一个给定的正整数a,
假设10^(x-1)<=a<10^x,那么显然a的位数为x位,
又因为
log10(10^(x-1))<=log10(a)<(log10(10^x))
即x-1<=log10(a)<x
则(int)log10(a)=x-1,
即(int)log10(a)+1=x
即a的位数是(int)log10(a)+1
我们知道了一个正整数a的位数等于(int)log10(a) + 1,
现在来求n的阶乘的位数:
假设A=n!=1*2*3*......*n,那么我们要求的就是
(int)log10(A)+1,而:
log10(A)
=log10(1*2*3*......n) (根据log10(a*b) = log10(a) + log10(b)有)
=log10(1)+log10(2)+log10(3)+......+log10(n)
现在我们终于找到方法,问题解决了,我们将求n的阶乘的位
数分解成了求n个数对10取对数的和,并且对于其中任意一个数,
都在正常的数字范围之类。
总结一下:n的阶乘的位数等于
(int)(log10(1)+log10(2)+log10(3)+......+log10(n)) + 1
5. 二进制枚举
//斯特林数判断阶乘位数
int n;
cin >> n;
for(int i = 0; i < (1<<n); i++) //遍历从0~2^n-1个状态,1取0不取
{
for(int j = 0; j < n; j++) //遍历二进制的每一位
{
if(i & (1 << j))
//1<<j输出一个n位中只有一位(第j位)为1的二进制数字,与i进行与运算,同1则为1来判断该位是否为1
//判断二进制第j位是否存在
{
printf("%d ",j);//如果存在输出第j个元素
}
}
printf("\n");
}
typedef struct node
{
int pi;
int di;
friend bool operator < (struct node a,struct node b)
{
return a.pi > b.pi;//按pi的值由小到大排序
}
}stone;
结构体变量是不能使用 < 比较的,必须重载
与sort不同,return a<b,返回的是一个递减的而不是递增的,因为优先队列中是要进行排序的,如果a小于b,返回一个真值,交换位置
-
洛谷 P2241 统计方形
(1)矩形数量 = 正方形数量 + 长方形数量
(2)对于矩形来说,固定右下角(i , j),那么矩形数量为 i * j。
链接:https://blog.youkuaiyun.com/qq_45260619/article/details/115342478?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link -
一个减少时间复杂度的巧妙方法
例如:有数组A[N],B[N],统计有多少对 (i,j) 整数满足 Ai=Bj?
解1(时间复杂度(n^2)):
解2(时间复杂度(n)):
long long ans=0;
vector<int> C(n; //由于n是可变的,所以这里设置动态数组,vector会自动给数组赋值0,所以不需要初始化
for(int j=0;j<N;j++)
C[B[j]]+=1;
for(int i=0;i<N;i++)
ans+=C[A[i]];
-
N的立方和
1的3次方+2的3次方+3的3次方+4的3次方+…+n的3次方
=(1+2+3+4+…+n)²
=[n*(n+1)/2]²
=(1/4)n²(n+1)² -
排列组合
(1)Amn(m上标,n下标)=n*(n-1)(n-2)(n-3)…(n-m+1),例如A58=87654(最后一项为8-5+1)
(2)Cmn(m上标,n下标)=[n(n-1)(n-2)(n-3)…(n-m+1]/123…m,例如C58=87654(最后一项为8-5+1)/12345(最后一项为m=5)。 -
判断一个函数成立的解
例如:求方程 a1x1−a2x2+a3x3−a4x4+a5x5−a6x6=0在 xi∈[1,k]内有多少组正整数解。
把式子转换一下
a1x1+a3x3+a5x5=a2x2+a4x4+a6x6
先预处理左边的,枚举左边的,用map记录答案出现的次数
再枚举右边,累加答案出现的次数
#include <bits/stdc++.h>
using namespace std;
int k,a1,a2,a3,a4,a5,a6;
map<int,int> v;
int main()
{
cin>>k>>a1>>a2>>a3>>a4>>a5>>a6;
for(int i=1;i<=k;i++)
for(int j=1;j<=k;j++)
for(int m=1;m<=k;m++)
{
int ans=a1*i+a3*j+a5*m;
v[ans]++;
}
int sum=0;
for(int i=1;i<=k;i++)
for(int j=1;j<=k;j++)
for(int m=1;m<=k;m++)
{
int ans=a2*i+a4*j+a6*m;
sum+=v[ans];
}
cout<<sum<<endl;
}