数学の入门到入土 第1天

第一类斯特林数的介绍(n^2)复杂度
例题链接[HDU 3625]Examining the Rooms

圆排列:把n个元素排在一个圆周上,如果旋转之后两个圆周上的排列一样,那么这两个排列相同 n个元素的圆排列=n-1个元素的排列数
第一类斯特林数S(n,m)表示把n个不同元素构成m个圆排列的方案数
由定义得S(n,0)=0,S(n,n)=1
第一类斯特林数有递推公式S(n,m)=S(n−1,m−1)+(n−1)×S(n−1,m)
证明:我们考虑把第n个元素放在什么位置。如果单独形成一个圆排列,则答案就是S(n-1,m-1).
如果插入到原来的m个圆排列中,那本质上就是在n-1个元素中选一个插到它后面去(定义“后面”为顺时针方向下一个数,定义为逆时针同理),有n-1种选法,答案就是(n-1)S(n-1,m)

n个房间都有钥匙,1号门不能破门而入,要打开其他门有一种环状关系 比方说第i号房间有第j号房间的钥匙,那么你就要去找第i号房间的钥匙的所在地或者破门而入 - - - - 总之理解一下这个连环关系

ll dp[50][50];
int main(){
ll t=read();


while(t--){
ll n=read();
ll k=read();
ll ans=1;
for(int i=0;i<=n;i++){
dp[i][0]=0;
dp[i][i]=1;
 for(int j=1;j<=i;j++){
  dp[i][j]=dp[i-1][j-1]+(i-1)*dp[i-1][j];
 }
}

for(int i=1;i<=n;i++){
    ans=ans*i;
}
ll add=0;
for(int i=1;i<=k;i++){
   add=add+dp[n][i]-dp[n-1][i-1];
}
double rnm=add*1.0/ans;
printf("%.4f\n",rnm);
}
return 0;
}

例题链接HDU 4372 Count the Buildings
n个房子 高度1–n 要你来重新排列这些房子 使得能够在某个房子处,从左看去有f个房子 从右看去有b个房子 的方案数
显然当我们在高度为n的房子时,左/右览都可以看完,那么以n为衔接点 分为两组 左边一组(x) 右边一组(y) 且满足x+y=n-1 (n定下来了,不考虑)
那么显然在n的两侧,只要两侧最值与n相邻,其余楼层随便排列即可 于是相当于要计算 第一类Stirling数 (n-1,x-1+y-1) *C(x-1+y-1,y-1); C是组合数计算式

ll dp[2001][2001];
ll c[2001][2001];
inline void pre(ll n){
    for(ll i=1; i<=n; i++) c[i][0]=1;
    dp[1][1]=c[1][1]=1;
    for(ll i=2; i<=n; i++){
        for(ll j=1; j<=i; j++){
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mods;
            dp[i][j]=(dp[i-1][j-1]+(i-1)*dp[i-1][j])%mods;
        }
    }
}

int main(){
ll t=read();
ll p=2000;
pre(p);
while(t--){
ll n=read();
ll f=read();
ll b=read();
if(f+b-2<=2000){
printf("%lld\n",dp[n-1][f+b-2]*c[f+b-2][b-1]%mods);
}
else{
    printf("0\n");
}
}
return 0;
}

第二类 Stirling数 简介
在这里插入图片描述
在这里插入图片描述
例题 HDU 2643
n个同学的排名情况总数 取模 排名可以并列
显然是一个n个不同的求放入n个可区分的盒子而且盒子可以空
那么直接套用第二类 Stirling数计算式

ll dp[2001][2001];
ll c[2001];
inline void pre(ll n){
    for(int i=1; i<=n; i++){
    dp[i][i]=dp[i][1]=1;
        for(int j=1;j<i;j++){
            dp[i][j]=(j*dp[i-1][j]%mods+dp[i-1][j-1])%mods;
        }
    }
}
int main(){
ll t=read();
ll op=150;
pre(op);
c[1]=1;
c[0]=1;
for(int i=1;i<=op;i++){
  c[i]=(c[i-1]*i)%mods;
}
while(t--){
  ll n=read();
  ll add=0;
  for(int i=1;i<=n;i++){

  add=(add+dp[n][i]*c[i]%mods)%mods;
  }
   printf("%lld\n",add);
}
return 0;
}

卡特兰数 (应用待更)

在这里插入图片描述
在这里插入图片描述

如何计算组合数 C(n,m,mod) 其中n,m,mod 范围很大 1e9

在这里插入图片描述
在此直接上exlucas 扩展定理
例题 HDU 3439
n个元素 1–n 全排列有n!种 ,我们要找恰好k个元素 即元素值与下标相等的方案数 对mod 取模
整体来看就是求C(n,k,mod)*H(n-k,mod)
H是错排函数

#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
 using namespace std;
inline ll read(){char c=getchar();ll f=1,x=0;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}return x*f;}
ll gcd(ll a,ll b){
    if(a<0)
    a=-a;
    if(b<0)
    b=-b;
    return b==0?a:gcd(b,a%b);
}
ll qpn(ll a,ll b, ll p){ll ans = 1;a%=p;while(b){if(b&1){ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元   (分子*qp(分母,mod-2,mod))%mod;
ll fact_pow(ll n,ll p)
{
    ll res=0;
    while(n)
    {
        n/=p;
        res+=n;
    }
    return res;
}
ll mult(ll a,ll b,ll p)
{
    a%=p;
    b%=p;
    ll r=0,v=a;
    while(b)
    {
        if(b&1)
        {
            r+=v;
            if(r>p)
                r-=p;
        }
        v<<=1;
        if(v>p)
            v-=p;
        b>>=1;
    }
    return r;
}
ll quick_pow(ll a,ll b,ll p)
{
    ll r=1,v=a%p;
    while(b)
    {
        if(b&1)
            r=mult(r,v,p);
        v=mult(v,v,p);
        b>>=1;
    }
    return r;
}

ll pow_mod(ll x,ll n,ll mod)
{
    ll res=1;
    while(n)
    {
        if(n&1)
            res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
        x=1,y=0;
        return;
    }
    exgcd(b,a%b,x,y);
    ll t=x;
    x=y,y=t-(a/b)*y;
}
ll INV(ll a,ll b)
{
    ll x,y;
    return exgcd(a,b,x,y),(x%b+b)%b;
}
ll crt(ll x,ll p,ll mod)
{
    return INV(p/mod,mod)*(p/mod)*x;
}
ll FAC(ll x,ll a,ll b)
{
    if(!x)
        return 1;
    ll ans=1;
    for(ll i=1; i<=b; i++)
        if(i%a)
            ans*=i,ans%=b;
    ans=pow_mod(ans,x/b,b);
    for(ll i=1; i<=x%b; i++)
        if(i%a)
            ans*=i,ans%=b;
    return ans*FAC(x/a,a,b)%b;
}
ll C(ll n,ll m,ll a,ll b)
{
    ll N=FAC(n,a,b),M=FAC(m,a,b),Z=FAC(n-m,a,b),sum=0,i;
    for(i=n; i; i=i/a)
        sum+=i/a;
    for(i=m; i; i=i/a)
        sum-=i/a;
    for(i=n-m; i; i=i/a)
        sum-=i/a;
    return N*pow_mod(a,sum,b)%b*INV(M,b)%b*INV(Z,b)%b;
}
ll exlucas(ll n,ll m,ll p)
{
    ll t=p,ans=0,i;
    for(i=2; i*i<=p; i++)
    {
        ll k=1;
        while(t%i==0)
        {
            k*=i,t/=i;
        }
        ans+=crt(C(n,m,i,k),p,k),ans%=p;
    }
    if(t>1)
        ans+=crt(C(n,m,t,t),p,t),ans%=p;
    return ans % p;
}
ll H(ll x,ll p)
{
       ll ans=0;
    if(x==0)return 1;
    x=x%(2*p);
    if(x==0)x=2*p;
    for(int i=2;i<=x;++i)
    ans=(ans*i+(i%2==0?1:-1))%p;
    return (ans+p)%p;
}

/*最小公倍数lcm(a,b)=a*b/gcd(a,b);
gcd(ka,kb)=k*gcd(a,b);
gcd(s/a,s/b)=s/gcd(a,b);
gcd(a,b)=gcd(a,b-a);
gcd(x^a-1,x^b-1)=x^gcd(a,b)-1;
gcd(f[a],f[b])=f[gcd(a,b)];
lcm(ka,kb)=k*lcm(a,b);
lcm(f[a],f[b])=f[lcm(a.b)];*/
int main(){
ll t=read();
ll add=0;
while(t--){
  add++;
 ll n=read();
 ll k=read();
 ll m=read();
 printf("Case %lld: %lld\n",add,exlucas(n,k,m)*H(n-k,m)%m);
}
return 0;
}

欧拉函数 phi(n) 表示小于n的数中 与n互质的数的个数
例题 LightOJ1370
对于a[]数组 给你n个数,定义F(x)=Σ num num∈phi(x) ;
要我们求出 每个phi(x)>=a[i] 时的F(x)值

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define Mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 1100000
using namespace std;
int T,n;
int phi[Maxn+1];//存欧拉函数
bool isPrime[Maxn+1];//存素数
int a[Maxn];
void Eular()//求欧拉函数
{
    for(int i=1;i<=Maxn;i++) phi[i]=i;
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0]=isPrime[1]=false;
    phi[1]=0;
    for(int i=2;i<=Maxn;i++)
    {
        if(isPrime[i])
        {
            for(int j=i;j<=Maxn;j+=i)
            {
                isPrime[j]=false;
                phi[j] -= phi[j]/i;
            }
        }
    }
}
int main()
{
    int Case=0;
    Eular();//打表
    cin>>T;
    while(T--)
    {
        MEM(a,0);
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        ll sum=0;
        sort(a,a+n);
        int pos=1;
        for(int i=0;i<n;i++)
        {
            for(int j=pos;j<Maxn;j++)
            {
                if(phi[j]>=a[i])
                {
                    sum+=j;
                    pos=j;
                    break;
                }
            }
        }
        printf("Case %d: %lld Xukha\n",++Case,sum);
    }
}

互质公式推导以及线性筛 例题CF D题 难度分2000
一个数num 他的质因子记为p1 —px 我们如果能从质因子中选出pi与pj
使得 gcd(pi+pj,num)=1 则输出pi pj 否则输出 -1
设 p1 , p2 , p3 , … , pm 为 ai 的质因子 , d1 = p1^k , d2 = ai / p1^k
其中 p1 为 ai 的最小质因子 , ai % p^k = 0 且 ai % p1^(k + 1) != 0
那么显然 (d1+d2)%p1≠0,(d1+d2)%p2≠0,…,(d1+d2)%pm≠0
所以 ai 的所有质因子 d1 + d2 都不包含 , 即 d1 + d2 与 ai 互质 ( 当 d2 = 1 时答案为 -1 )
而本题数据范围很大 , 所以我们得先用线性筛找出 1 ~ 1e7 内每个数的 p1 然后再操作

#include<bits/stdc++.h>
using namespace std;
int prime[10000100],minprime[10000100];
int euler(int n)
{
    int c = 0;
    for(int i = 2 ; i <= n ; i ++)
    {
        if(!minprime[i]) prime[++ c] = i , minprime[i] = i;
        for(int j = 1 ; j <= c && i * prime[j] <= n ; j++)
        {
            minprime[i * prime[j]] = prime[j];
            if(i % prime[j] == 0) break;
        }
    }
    return c;
}
const int N = 5e5 + 10;
int n , a[N] , ans[N][2];
signed main()
{
    ios::sync_with_stdio(false);
    euler(1e7);
    cin >> n;
    for(int i = 1 ; i <= n ; i ++) cin >> a[i];
    for(int i = 1 ; i <= n ; i ++)
    {
        int x = a[i] , now = 1 , mi = minprime[x];
        while(x % mi == 0) x /= mi , now *= mi;
        if(now != 1 && x != 1) ans[i][0] = now , ans[i][1] = x;
        else ans[i][0] = -1 , ans[i][1] = -1;
    }
    for(int j = 0 ; j <= 1 ; j ++)
    {
        for(int i = 1 ; i <= n ; i ++) cout << ans[i][j] << " ";
        cout << '\n';
    }
    return 0;
}

今日止步 二分图算法 再接再厉吧 ,晚上学习二分图算法
未AC的题 分解质因子+HK算法
这个题卡了匈牙利算法 QAQ
在这里插入图片描述
每天都要努力啊 !

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Simulink是一款强大的仿真工具,用于设计、模拟和分析各种系统的行为。下面是一个从入门入土的Simulink仿真教程。 1. 软件安装:首先需要下载和安装Simulink软件。在MathWorks官方网站上找到适合的版本,并按照指示进行安装。 2. Simulink基础:打开Simulink后,可以看到一个模块化的仿真环境。了解基本的Simulink界面、工具栏和库,这些是使用Simulink进行仿真的基础。 3. 模型建立:使用Simulink可以通过将各种模块组合在一起来建立模型。通过从库中拖拽模块到仿真界面,使用线连接相应的模块,可以构建出一个完整的系统模型。 4. 参数设置:对于每个模块,都可以设置相应的参数。这些参数可根据需要进行调整,以便模型可以更准确地模拟真实系统的行为。 5. 信号输入:创建一个仿真的关键是提供输入信号。可以通过添加信号源模块来生成不同类型的输入信号,如恒定值、正弦波、脉冲等。 6. 仿真运行:配置好模型和输入信号后,可以点击运行按钮开始仿真。仿真结果将在仿真器窗口中显示,此时可以观察系统的行为。 7. 结果分析:Simulink提供了多种工具用于分析仿真结果。可以绘制输出信号的波形图,计算系统的响应时间、频率响应等。 8. 优化改进:根据分析结果,可以调整模型参数以改进系统的性能。这包括调整模块参数、修改模型结构等。 9. 进阶功能:通过进一步学习和实践,还可以掌握更高级的Simulink功能,如使用MATLAB脚本进行仿真、使用状态流图进行建模等。 10. 深入学习:要真正掌握Simulink,需要不断深入学习和实践。可以参考Simulink的官方文档、视频教程和论坛,以及阅读相关书籍。 总之,通过上述步骤,您可以从入门入土地掌握Simulink的基本原理和使用方法,能够进行各种系统模型的建立和仿真。但记住,Simulink只是一个工具,对于真正理解和解决复杂系统问题,还需要深入学习掌握相关的系统理论和建模方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值