zoukankan      html  css  js  c++  java
  • luogu1771 方程的解

    题目大意

    对于不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整数,g(x)=x^x mod 1000(即x^x除以1000的余数),x,k是给定的数。我们要求的是这个不定方程的正整数解组数。

    DP(暴力)解法

    定义F(p, rest)为第p个数,p及p后面的数的和为rest的解的数量,递归式为:F(p, rest)=if(rest==0)0 else if (p == k) rest else sum foreach curVal(0<curVal<=rest) F(p, rest - curVal)。

    不用高精度,本方法能得40分。

    注意

    curVal<=rest就可以了,反正如果curVal大了以后也能返回0,不要擅自进一步缩小curVal的范围。

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    #define ll long long
    #define _NDEBUG
    
    const int MAX_K = 110, MAX_X = 1010, P = 1000;
    ll F[MAX_K][MAX_X];
    ll K, X;
    
    ll Mult(ll a, ll b, ll p)
    {
    	ll ans = 0;
    	while (b)
    	{
    		if (b & 1)
    			ans = (ans + a) % p;
    		a = (a + a) % p;
    		b >>= 1;
    	}
    	return ans;
    }
    
    ll Power(int a, int n, int p)
    {
    	ll ans = 1;
    	while (n)
    	{
    		if (n & 1)
    			ans = Mult(ans, a, p);
    		a = Mult(a, a, p);
    		n >>= 1;
    	}
    	return ans;
    }
    
    ll DP(int p, ll rest)
    {
    	if (F[p][rest] != -1)
    		return F[p][rest];
    	if (rest == 0)
    		return F[p][rest] = 0;
    	if (p == K)
    		return F[p][rest] = 1;
    	F[p][rest] = 0;
    	for (int i = 1; i <= rest; i++)
    		F[p][rest] += DP(p + 1, rest - i);
    	return F[p][rest];
    }
    
    int main()
    {
    	scanf("%lld%lld", &K, &X);
    	memset(F, -1, sizeof(F));
    	printf("%lld
    ", DP(1, Power(X, X, P)));
    	return 0;
    }
    

    组合数学解法

    把x^x%1000看作一个线段,a1,a2...看作一个个隔板划分出的区域,这就是组合数学中的隔板模型,最终结果为C(k,x^x%1000)

    注意

    • 求组合数的模板就这样定死了,不要改。
    • 高精度里最好把=运算符写上。
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define ll long long
    
    const int MAX_K = 110, MAX_X = 1010, P = 1000, BASE = 10000, CARRY = 4, MAX_LEN = 1010;
    ll K, X;
    
    ll Mult(ll a, ll b, ll p)
    {
    	ll ans = 0;
    	while (b)
    	{
    		if (b & 1)
    			ans = (ans + a) % p;
    		a = (a + a) % p;
    		b >>= 1;
    	}
    	return ans;
    }
    
    ll Power(int a, int n, int p)
    {
    	ll ans = 1;
    	while (n)
    	{
    		if (n & 1)
    			ans = Mult(ans, a, p);
    		a = Mult(a, a, p);
    		n >>= 1;
    	}
    	return ans;
    }
    
    struct BigInt
    {
    private:
    	int A[MAX_LEN];
    	int Len;
    
    public:
    	void Clear()
    	{
    		memset(A, 0, sizeof(A));
    		Len = 0;
    	}
    
    	void Set(int x)
    	{
    		Clear();
    		while (x)
    		{
    			A[Len++] = x%BASE;
    			x /= BASE;
    		}
    		while (A[Len] == 0 && Len > 0)
    			Len--;
    	}
    
    	BigInt() { Clear(); }
    
    	BigInt operator = (const int x)
    	{
    		Set(x);
    		return *this;
    	}
    
    	BigInt operator = (const BigInt &a)
    	{
    		memcpy(A, a.A, sizeof(A));
    		Len = a.Len;
    		return *this;
    	}
    
    	void Print()
    	{
    		printf("%d", A[Len]);
    		for (int i = Len - 1; i >= 0; i--)
    			printf("%0*d", CARRY, A[i]);
    		printf("
    ");
    	}
    
    	BigInt operator += (const BigInt &a)
    	{
    		Len = max(Len, a.Len);
    		for (int i = 0; i <= Len; i++)
    		{
    			A[i] += a.A[i];
    			A[i + 1] += A[i] / BASE;
    			A[i] %= BASE;
    		}
    		if (A[Len + 1])
    			Len++;
    		return *this;
    	}
    
    	BigInt operator + (const BigInt &a)
    	{
    		BigInt Num = *this;
    		return Num += a;
    	}
    };
    
    BigInt Comb(int r, int n)
    {
    	static BigInt C[MAX_K];
    	C[0] = 1;
    	for (int i = 1; i <= n; i++)
    	{
    		for (int j = min(r, i); j > 0; j--)
    		{
    			if (i == j)
    				C[j] = 1;
    			else
    				C[j] = C[j - 1] + C[j];
    		}
    	}
    	return C[r];
    }
    
    int main()
    {
    	scanf("%lld%lld", &K, &X);
    	Comb(K - 1, Power(X,X,P) - 1).Print();
    	return 0;
    }
    

      

  • 相关阅读:
    20162317袁逸灏 第十六周实验报告:实验五 网络编程与安全
    20162317-20162315结对编程-四则运算(挑战出题)
    第十四周实验报告:实验四 Android程序设计
    20162305 2016-2017-2 《程序设计与数据结构》第9周学习总结
    20162305 2016-2017-2 《程序设计与数据结构》第8周学习总结
    20162305 实验二 Java面向对象程序设计 实验报告
    20162305 2016-2017-2 《程序设计与数据结构》第7周学习总结
    20162305 2016-2017-2 《程序设计与数据结构》第6周学习总结
    20162305 2016-2017-2 《程序设计与数据结构》第5周学习总结
    20162305 李昱兴 实验报告一
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8886493.html
Copyright © 2011-2022 走看看