列表

详情


NC15415. Equation and Inequation

描述

You are given an equation x1 + x2 + x3 + ... + xk = s. And also m inequations such as xi = xj, xi ≤ xj, xi ≥ xj, xi ≥ xj, xi < xj and xi > xj.

Count the number of positive solutions satisfying all the constraints.

输入描述

The input will consist of multiple test cases.
Each case begins with three integers s, k, and m (1 ≤ k ≤ 12, 1 ≤ s ≤ 10^9, 1 ≤ m ≤ 100). The following m lines describe the inequations in such format: "i op j" (without quotes), where "op" is one of the following signs("=", "!=", "<=", ">=", "<", ">").
The number of test cases is less than 1500. For 95% of the test cases, k ≤ 7.

输出描述

For each test case print the answer (number of solutions modulo 10^9+7) in one line.

示例1

输入:

3 2 1
1 != 2
3 2 1
1 = 2
50 6 5
1 < 2
1 != 3
3 <= 2
2 = 4
5 >= 6
1000000000 8 12
8 >= 8
2 >= 6
6 != 2
4 = 4
2 < 7
4 <= 1
4 <= 5
1 >= 1
6 <= 1
7 >= 6
8 < 4
4 <= 2

输出:

2
0
7700
396619262

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1634ms, 内存消耗: 3052K, 提交时间: 2018-04-01 11:19:32

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<assert.h>

#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

template<typename T>inline void upmin(T &x,T y) { y<x?x=y:0; }
template<typename T>inline void upmax(T &x,T y) { x<y?x=y:0; }

typedef unsigned int u32;
typedef long long LL;
typedef unsigned long long ULL;
typedef long long ll;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;

const lod pi=acos(-1);
const int oo=1<<30;
const LL OO=1e18;

const int lim=161;
int u[110],v[110],op[110];
int f[1<<12][lim];
int sum[lim];
const int mod=1e9+7;
#define MOD mod
namespace linear_seq {
	const int LMAXN = 10010;
	ll res[LMAXN], base[LMAXN], _c[LMAXN], _md[LMAXN];
	vector<ll> Md;

	ll pw(ll a, ll b) {
		ll res = 1;
		a %= MOD;
		for(; b; b >>= 1) {
			if(b & 1) res = res * a % MOD;
			a = a * a % MOD;
		}
		return res;
	}

	void mul(ll *a, ll *b, ll k) {
		for(int i = 0; i < k + k; i++) _c[i] = 0;
		for(int i = 0; i < k; i++) if(a[i]) {
				for(int j = 0; j < k; j++) {
					_c[i + j] = (_c[i + j] + a[i] * b[j]) % MOD;
				}
			}
		for(int i = k + k - 1; i >= k; i--) if(_c[i]) {
				for(int j = 0; j < (int)Md.size(); j++) {
					_c[i - k + Md[j]] = (_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % MOD;
				}
			}
		for(int i = 0; i < k; i++) a[i] = _c[i];
	}

	ll solve(ll n, vector<ll> a, vector<ll> b) {
		ll ans = 0, pnt = 0;
		int k = a.size();
		for(int i = 0; i < k; i++) {
			_md[k - 1 - i] = -a[i];
		}
		_md[k] = 1;
		Md.clear();
		for(int i = 0; i < k; i++) if(_md[i]) {
				Md.push_back(i);
			}
		for(int i = 0; i < k; i++) res[i] = base[i] = 0;
		res[0] = 1;
		while((1LL << pnt) <= n) pnt++;
		for(int p = pnt; p >= 0; p--) {
			mul(res, res, k);
			if((n >> p) & 1) {
				for(int i = k - 1; i >= 0; i--) {
					res[i + 1] = res[i];
				}
				res[0] = 0;
				for(int j = 0; j < (int)Md.size(); j++) {
					res[Md[j]] = (res[Md[j]] - res[k] * _md[Md[j]]) % MOD;
				}
			}
		}
		for(int i = 0; i < k; i++) {
			ans = (ans + res[i] * b[i]) % MOD;
		}
		if(ans < 0) ans += MOD;
		return ans;
	}

	vector<ll> BM(vector<ll> s) {
		vector<ll> C(1, 1), B(1, 1);
		ll L = 0, m = 1, b = 1;
		for(int n = 0; n < (int)s.size(); n++) {
			ll d = 0;
			for(int i = 0; i < L + 1; i++) {
				d = (d + C[i] * s[n - i]) % MOD;
			}
			if(!d) ++m;
			else if(2 * L <= n) {
				vector<ll> T = C;
				ll c = MOD - d * pw(b, MOD - 2) % MOD;
				while(C.size() < B.size() + m) C.push_back(0);
				for(int i = 0; i < (int)B.size(); i++) {
					C[i + m] = (C[i + m] + c * B[i]) % MOD;
				}
				L = n + 1 - L; B = T; b = d; m = 1;
			} else {
				ll c = MOD - d * pw(b, MOD - 2) % MOD;
				while(C.size() < B.size() + m) C.push_back(0);
				for(int i = 0; i < (int)B.size(); i++) {
					C[i + m] = (C[i + m] + c * B[i]) % MOD;
				}
				++m;
			}
		}
		return C;
	}

	ll work(vector<ll> a, ll n) {
		vector<ll> c = BM(a);
		c.erase(c.begin());
		for(int i = 0; i < (int)c.size(); i++) {
			c[i] = (MOD - c[i]) % MOD;
		}
		return solve(n, c, vector<ll>(a.begin(), a.begin() + c.size()));
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
#endif
	int n,all,m,i,j,s,t,o,cur;char c;
	while (cin>>all>>n>>m) {
		for (s=0;s<1<<n;s++)
			for (i=0;i<lim;i++)
				f[s][i]=0;
		for (i=1;i<=m;i++) {
			cin>>u[i];u[i]--;
			while (1) {
				if ((c=getchar())=='=')
					op[i]=1;
				else if (c=='!') getchar(),op[i]=2;
				else
					if (c=='<')
						if (getchar()=='=') op[i]=3;
						else op[i]=5;
					else if (c=='>')
						if (getchar()=='=') op[i]=4;
						else op[i]=6;
					else continue;
				break;
			}
			cin>>v[i];v[i]--;
			if (op[i]==4) op[i]=3,swap(u[i],v[i]);
			if (op[i]==6) op[i]=5,swap(u[i],v[i]);
		}
		f[0][0]=1;
		for (s=0;(s+1)<1<<n;s++) {
			cur=n-__builtin_popcount(s);
			for (j=0;j<lim;j++) {
				sum[j]=f[s][j];
				if (j>=cur) (sum[j]+=sum[j-cur])%=mod;
			}
			for (o=t=((1<<n)-1)^s;t;(--t)&=o) {
				for (i=1;i<=m;i++) {
					if (op[i]==1&&(t>>u[i]&1)!=(t>>v[i]&1)) break;
					if (op[i]==2&&(t>>u[i]&1)&&(t>>v[i]&1)) break;
					if (op[i]==3&&(t>>u[i]&1)&&(s>>v[i]&1)) break;
					if (op[i]==3&&(t>>v[i]&1)&&!((s|t)>>u[i]&1)) break;
					if (op[i]==5&&(t>>u[i]&1)&&((s|t)>>v[i]&1)) break;
					if (op[i]==5&&(t>>v[i]&1)&&!(s>>u[i]&1)) break;
				}
				if (i>m)
					for (i=cur;i<lim;i++)
						(f[s|t][i]+=sum[i-cur])%=mod;
			}
		}
		vector<LL>v;
		for (i=1;i<lim;i++) v.pb(f[s][i]);
		printf("%lld\n",linear_seq::work(v,all-1));
	}
	
	return 0;
}

上一题