数学

概要

level 1: GCD , LCM ,素数判定 , 埃氏筛
level 2 : 整数拆分 exgcd 欧拉筛(线性筛)


`

数学基本巧妙思路

加减妙法:
构建负数 再用减法
在这里插入图片描述基本思路:分两种情况::
1.m=0 没有减号 则全部相加
2.有减号 则构造负数 但减号必须会生效一次 要求最大值 则贪心 舍弃掉最小数(排序)
在这里插入图片描述
在这里插入图片描述

#include"bits/stdc++.h"

using namespace std;
const int N = 2e5 + 10;
int a[N];
int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n + m + 1; i ++)
    {
         scanf("%d", &a[i]);
    }
    int len = n + m + 1;
    sort(a + 1, a + 1 + len);
    long long res = 0;
   if(!m)
   {
       for(int i = 1; i <= len ;i ++)res += a[i];
   }
    else
    {
        res += a[len] - a[1];
        for(int i = 2; i < len ;i ++)
            res += abs(a[i]);
    }
    cout << res;
}

容斥原理

提示:简记容斥原理:奇加偶减。
已知:需要求解的是不含"c",“o”,"w"的字符串的数量。
计算贡献:将题目要求换一种表述方式。
求解的个数:不含"c"或者不含"o"或者不含"w"的字符串的数量。
So
不含"c"或者不含"o"或者不含"w"的数量 = 不含"c"的数量 + 不含"o"的数量 + 不含"w"的数量 − 不含"c"并且不含"o"的数量 − 不含"o"并且不含"w"的数量 − 不含"c"并且不含"w"的数量 + 不含"c"并且不含"o"并且不含"w"的数量。
由于不含一个字母的个数都相同,不含两个字母的个数也相同。
所以等式变为:
不含"c"或者不含"o"或者不含"w"的数量 = 3× ×不含"c"的数量 − 3×不含"c"并且不含"o"的数量 + 不含"c"并且不含"o"并且不含"w"的数量

答案=
C(3,2)*可能含有两个非法字符的方案数
-C(3,1)*可能含有一个非法字符的方案数
+C(3,0)*不含非法字符的方案数
=C(3,2)*pow(25,n) - C(3,1)*pow(24,n) + C(3,0)*pow(23,n);
直接快速幂求解,复杂度logn。

在这里插入图片描述
代码实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll qmi(int x,int y){
	ll res=0;
	while(y){
		if(y&1)res=res*x%mod;
		a=a*a%mod;
		y>>=1;
	}
	return res;
}
int main()
{
	int n;
	cin>>n;
	ll ans=3*qmi(25,n)%mod-3*qmi(24,n)%mod+qmi(23,n)%mod;
	ans=(ans%mod+mod)%mod;
	cout<<ans<<endl;
	return 0;
}

法二:dp

dp[i][j] 前i个字符出现了 j 种 禁忌字符,注意是种,所以递推方程就不难推了。
复杂度On。

#include<bits/stdc++.h>
using namespace std;
const int maxx=2e5+7;
const long long ll;
const ll mod=1e9+7;
ll dp[maxx][3];//含义为前i个里面包含有j个禁忌字符
int n;
int main()
{
	cin>>n;
	dp[1][0]=23;dp[1][1]=3;dp[1][2]=0;
	for(int i=2;i<=n;i++){
		dp[i][0]=dp[i-1][0]*23;
		dp[i][1]=dp[i-1][0]*3+dp[i-1][1]*25;
		dp[i][2]=dp[i-1][1]*2+dp[i-1][2]*25;
	}
	printf("%lld\n",(dp[n][0]+dp[n][1]+dp[n][2])%mod);
}

数论

质数判定
时间复杂度为o(log n /3)

bool isPrime_3( int num )
{
                 //两个较小数另外处理
                 if(num ==2|| num==3 )
                                 return 1 ;
                 //不在6的倍数两侧的一定不是质数
                 if(num %6!= 1&&num %6!= 5)
                                 return 0 ;
                 int tmp =sqrt( num);
                 //在6的倍数两侧的也可能不是质数
                 for(int i= 5;i <=tmp; i+=6 )
                                 if(num %i== 0||num %(i+ 2)==0 )
                                                 return 0 ;
                 //排除所有,剩余的是质数
                 return 1 ;
}

扩展欧几里得算法

例一:包子凑数(扩展欧几里得+完全背包)
在这里插入图片描述

例二:
在这里插入图片描述
解题思路:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值