1. 程式人生 > 實用技巧 >【數學】一次不定方程非負整數解個數

【數學】一次不定方程非負整數解個數

一次不定方程非負整數解個數

前置定理:

  • \(\frac{1}{1-x}=\sum^{\infty}_{r=0}x^r\)

  • \(\frac{1}{1-sx}=\sum^{\infty}_{r=0}s^rx^r\)

  • \(\frac{1}{(1-x)^n}=\sum^{\infty}_{r=0}C^{n-1}_{n+r-1}x^r=\sum^{\infty}_{r=0}C^{r}_{n+r-1}x^r\)

  • 定理 \(1\)

    一次不定方程

    \[x_1+x_2+\dots+x_n=r\tag{1.1} \]

    的非負整數解的個數等於 \(C_{n+r-1}^r=C_{n+r-1}^{n-1}\)

    .

    證:

    設方程 \((1.1)\)\(a_r\) 個非負整數解。 不難發現,數列 \(a_0,a_1,a_2,\dots,a_r,\dots\) 的母函式就是

    \[\underbrace{(1+x+x^2+\dots+x^k+\dots)(1+x+x^2+\dots+x^k+\dots)\dots\\(1+x+x^2+\dots+x^k+\dots)}_{n 個}\tag{1.2} \]

    事實上,式 \((1,2)\) 的展開式中每個 \(x^r\) 必可寫成

    \[x^r=x^{m_1}\cdot x^{m_2}\dots x^{m_n}=x^{m_1+m_2+\dots+m_n}\tag{1.3} \]

    這裡 \(x^{m_1},x^{m_2},\dots,x^{m_n}\) 分別取自第 \(1,2,\dots,n\) 個括號,顯然 \(m_1,m_2\dots,m_n\) 都是非負整數。由式 \((1.3)\) 可知

    \[m_1+m_2+\dots+m_n=r \]

    \((m_1,m_2,\dots,m_n)\) 是方程 \((1.1)\) 的一個非負整數解。 這就是說式 \((1.2)\) 中每一項 \(x^r\) 對應方程 \((1.1)\) 的一個非負整數解 \((m_1,m_2,\dots,m_n)\) ;方程 \((1.1)\) 的每一個非負整數解也對應式 \((1.2)\) 的一項 \(x^r\)

    。因此方程 \((1.1)\) 的非負整數解的個數 \(a_r\) 就等於式 \((1.2)\)\(x^r\) 的項數。合併同類項後, \(a_r\) 就等於 \(x^r\) 的係數。從而式 \((1.2)\) 就是 \(\{a_r\}\) 的母函式。

    又式 \((1.2)\) 等於 \(\frac{1}{1-x}\cdot\frac{1}{1-x}\dots\frac{1}{1-x}=\frac{1}{(1-x)^n}\) ,即

    \[\frac{1}{(1-x)^n}=a_0+a_1x+a_2x^2+\dots+a_rx^r\dots\;, \]

    故由前置定理可得

    \[a_r=C^{r}_{n+r-1}\;(r=0,1,2,\dots) \]

  • 推論:

    不定方程 \(x_1+x_2+\dots+x_n=r\) 的正整數解的個數為 \(C^{n-1}_{r-1}\)

    證:

    作變換:\(x_1=y_1+1,x_2=y_2+1,\dots,x_n=y_n+1\) ,則原方程可化為

    \[y_1+y_2+\dots+y_n=r-n . \]

    \(x_1,x_2\dots,x_n\) 取正整數時,\(y_1,y_2,\dots,y_n\) 取非負整數值。這樣問題就轉化為求上面關於 \(y_1,y_2,\dots,y_n\) 的方程的非負整數解的個數。由定理 \(1\) 可知非負整數解的個數為

    \[C^{r-n}_{n+(r-n)-1}=C^{r-n}_{r-1}=C_{r-1}^{n-1 } . \]

  • 定理 \(2\)

    設方程 \(s_1x_1+s_2x_2+\dots+s_nx_n=r\) 的非負整數解的個數為 \(b\) ,則 \(b_r\) 的母函式是

    \[\frac{1}{(1-x^{s_1})(1-x^{s_2})\dots(1-x^{s_n})} \]

    這裡 \(s_1,s_2,\dots,s_n\) 都是正整數。

  • \(1\)

    試求方程 \(x+y+z=24\) 的整數解的個數,要求 \(x>1,y>2,z>3\)

    解:

    作變換: \(x=X+2,y=Y+3,z=Z+4\) ,則問題轉化為求方程 \(X+Y+Z=15\) 的非負整數解的個數。由定理 \(1\) ,得解的個數為

    \[C^{15}_{3+15-1}=C^{2}_{17}=136 \]

  • \(2\)

    試求方程 \(x_1+x_2+x_3+x_4=23\) 的正整數解的個數,要求 \(x_1\leq9,x_2\leq8,x_3\leq7,x_4\leq6\)

    解:

    設方程 \(x_1+x_2+x_3+x_4=r\) 滿足條件的 \(x_1\leq9,x_2\leq8,x_3\leq7,x_4\leq6\) 的正整數解的個數為 \(a_r\) ,則 \(a_r\) 的母函式為

    \[(x+x^2+\dots+x^9)(x+x^2+\dots+x^8)(x+x^2\dots+x^7)(x+x^2+\dots+x^6) \]

    易知上式的展開式中 \(x^{23}\) 的係數 \(a_{23}\) 就是問題的解。而 \(a_{23}\) 又是

    \[f(x)=(1+x+x^2+\dots+x^8)(1+x+x^2+\dots+x^7)\\(1+x+x^2\dots+x^6)(1+x+x^2+\dots+x^5) \]

    的展開式中 \(x^{19}\) 的係數,上式等於

    \[f(x)=\frac{(1-x^9)(1-x^8)(1-x^7)(1-x^6)}{(1-x)^4} \]

    因為 \(\frac{1}{(1-x)^4}=\sum_{r=0}^{\infty}C_{r+3}^3x^r\) ,把 \(f(x)\) 的分子展開,並去掉次數高於 \(19\) 的項,問題就轉化為求

    \[(1-x^6-x^7-x^8-x^9+x^{13}+x^{14}+2x^{15}+x^{16}+x^{17})\sum_{r=0}^{\infty}C_{r+3}^3x^r \]

    展開式中 \(x^{19}\) 的係數,易知它等於

    \[C_{22}^3-C_{16}^3-C_{15}^3-C_{14}^3-C_{13}^3+C_9^3+C_8^3+2C_7^3+C_6^3+C_5^3=115 \]

  • 例題

    1,P3301 方程

    題意:

    給定方程

    \[X_1+X_2+\dots+X_n=M \]

    有限制如下:

    \[\begin{align*} &X_1\leq A_1\\&X_2\leq A_2\\&\dots\\&X_{n_1}\leq A_{n_1},\\\\&X_{n_1+1}\geq A_{n_1+1}\\&X_{n_1+2}\geq A_{n_1+2}\\&\dots\\&X_{n_1+n_2}\geq A_{n_1+n_2} \end{align*} \]

    其中 $n_1+n_2\leq n,;n\leq 1e^9,n_1\leq8,n_2\leq8,m\leq1e^9 $。

    求:滿足這些限制的前提下,該方程正整數解的個數。答案對 \(p\) 取模。 \(p\in\{10007,262203414,437367875\}\)

    解:

    對於所有含限制 \(X_i\geq A_i\)\(X_i\) 做變換:

    \[X_i=X_i-A_i\\M-=A_i \]

    \(X_i\) 的限制變為 \(X_i\geq0\)

    則,給定方程的解的個數 \(a_M\)

    \[\begin{align*} f(x)&=\frac{1}{(1-x)^{n-n_1}}\times \frac{\prod_{i=1}^{n_1}(1-x^{A_i})}{(1-x)^{n_1}}\\&=\frac{\prod_{i=1}^{n_1}(1-x^{A_i})}{(1-x)^n} \end{align*} \]

    的展開式中 \(x^{M}\) 的係數。

    剩下做法同例2。

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mkp(a,b) make_pair(a,b)
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    const int inf=0x3f3f3f3f;
    
    ll exgcd(ll a,ll b,ll &x,ll &y){
        if(!b){
            x=1;y=0;
            return a;
        }
        ll g=exgcd(b,a%b,x,y);
        ll t=x;
        x=y;
        y=t-a/b*y;
        return g;
    }
    
    ll inv(ll a,ll b)
    {
        ll x=0,y=0;
        exgcd(a,b,x,y);
        x=(x%b+b)%b;
        if(!x)x+=b;
        return x;
    }
    
    ll kpow(ll a,ll b,ll p)
    {
        ll ans=1;
        while(b){
            if(b&1)ans=ans*a%p;
            a=a*a%p;
            b>>=1;
        }
        return ans;
    }
    ll Y[maxn];
    ll calc(ll n,ll p,ll pk,ll yy)
    {
        if(!n)return 1;
        ll x=calc(n/p,p,pk,yy),y=1;
        ll z=1;
    //    for(ll i=1;i<=pk;i++)
    //        if(i%p)y=y*i%pk;
        y=kpow(yy,n/pk,pk);
        for(ll i=n/pk*pk;i<=n;i++)
            if(i%p)z=z*i%pk;
        return x*y%pk*z%pk;
    }
    ll G(ll n,ll p){
        if(n<p)return 0;
        return n/p+G(n/p,p);
    }
    ll fac[maxn],w[maxn],b[maxn],k,tw[maxn];
    ll exLucas(ll n,ll m,ll p)
    {
        for(int i=1;i<=k;i++)
        {
        	tw[i]=w[i];
            b[i]=kpow(fac[i],G(n,fac[i])-G(m,fac[i])-G(n-m,fac[i]),w[i]);
            b[i]=b[i]*calc(n,fac[i],w[i],Y[i])%w[i]*inv(calc(m,fac[i],w[i],Y[i]),w[i])%w[i]*inv(calc(n-m,fac[i],w[i],Y[i]),w[i])%w[i];
        }
        ll d;
        for(int i=2;i<=k;i++)
        {
            d=__gcd(tw[i-1],tw[i]);
            b[i]=inv(tw[i-1]/d,tw[i]/d)*((b[i]-b[i-1])/d)%(tw[i]/d)*tw[i-1]+b[i-1];
            tw[i]=tw[i-1]*tw[i]/d;
            b[i]=(b[i]%tw[i]+tw[i])%tw[i];
        }
        return b[k];
    }
    
    
    ll A[maxn];
    map<ll,ll>mp,tmp;// <指數,係數>
    int main()
    {
    	int T,p,pp;
    	scanf("%d%d",&T,&p);
    	pp=p;k=0;
    	for(int i=2,t;i*i<=pp;i++)
    		if(pp%i==0){
    			t=1;
    			while(pp%i==0)pp/=i,t*=i;
    			w[++k]=t;fac[k]=i;
    		}
    	if(pp!=1){
    		w[++k]=pp;fac[k]=pp;
    	}
    	for(int i=1;i<=k;i++)
    	{
    		Y[i]=1;
    		for(ll j=1;j<=w[i];j++)
            	if(j%fac[i])Y[i]=Y[i]*j%w[i];
    	}
    	while(T--)
    	{
    		mp.clear();
    		ll n,n1,n2,m,x,r;
    		scanf("%lld%lld%lld%lld",&n,&n1,&n2,&m);
    		for(int i=1;i<=n1;i++)scanf("%lld",&A[i]);
    		for(int i=1;i<=n2;i++){
    			scanf("%lld",&x);
    			m-=x;
    		}
    		m-=(n-n2);
    		if(m<0){
    			puts("0");continue;
    		}
    		mp[0]=1;
    		ll c,d;
    		for(int i=1;i<=n1;i++)
    		{
    			tmp.clear();
    			for(auto x:mp){
    				c=x.first;d=x.second;// dx^c - dx^(c+a[i]) 
    				tmp[c]+=d;
    				tmp[c+A[i]]-=d;
    			}
    			mp=tmp;
    		}
    		ll res=0;
    		for(auto x:mp){
    			c=x.first;d=x.second;
    			if(c>m)continue;
    			r=m-c;
    			res=(res+d*exLucas(n+r-1,n-1,p)%p+p)%p;
    		}
    		printf("%lld\n",res);
    	}
    }
    

    2,揹包

    題意:

    給定方程:

    \[x_1+x_2+x_3+2x_4+2x_5+1+4x_6+x_7+3x_8=n \]

    亦即:

    \[x_1+x_2+x_3+2x_4+2x_5+4x_6+x_7+3x_8=n-1 \]

    其中,限制:

    \[x_1\leq 1\\x_2\leq2\\x_3\leq 3\\x_7\leq1 \]

    求解方程非負整數解個數。

    解:

    對於 \(x_1+x_2+x_3+x_7\) 有母函式:

    \[(1+x)(1+x+x^2)(1+x+x^2+x^3)(1+x) \]

    即:

    \[\frac{(1-x^2)(1-x^3)(1-x^4)(1-x^2)}{(1-x)^4} \]

    對於 \(2x_4+2x_5+4x_6+3x_8\) 有母函式(定理2):

    \[\frac{1}{(1-x^2)(1-x^2)(1-x^4)(1-x^3)} \]

    則,對於原方程有母函式:

    \[\begin{align*} f(x)&=\frac{(1-x^2)(1-x^3)(1-x^4)(1-x^2)}{(1-x)^4}\times\frac{1}{(1-x^2)(1-x^2)(1-x^4)(1-x^3)}\\ &=\frac{1}{(1-x)^4} \end{align*} \]

    則,原方程的解的個數為 \(f(x)\)\(x^{n-1}\) 的係數,即 \(C_{4+(n-1)-1}^{3}=C_{n+2}^3\)

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mkp(a,b) make_pair(a,b)
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    
    int c[4]={1,1,500000004,333333336};
    int main()
    {
    	ll n;
    	scanf("%lld",&n);
    	ll res=1;
    	for(ll i=n+2,j=1;j<=3;i--,j++)res=res*(i%mod)%mod*c[j]%mod;
    	printf("%lld\n",res);
    }