Codeforces 1111D

链接:https://codeforces.com/contest/1111/problem/D

题意有点复杂,这里不说了

主要是这里学习到了一个思想,这个思想和背包的过程是互通的:

使用前i+1个物品达成j点消费的方法数=

只使用前i个物品的方法数+使用了第(i+1)个物品的方法数=

只是用前i个物品的方法数+使用前i个物品达成(j-Cost[i+1])的方法数

代码: 

//Problem:
//Date:
//Skill:
//Bug:
/////////////////////////////////////////Definations/////////////////////////////////////////////////
//循环控制
#define CLR(a) memset((a),0,sizeof(a))
#define RE(i,n)  for(int i=0;i<int(n);i++)
#define RE2(i,n) for(int i=1;i<=int(n);i++)
#define FOR(x,vec) for(vector<int>::iterator it=vec.begin();it!=vec.end();++it) { int &x(*it);
//输入输出
#define INC(c) do{scanf("%c",&c);}while(isspace(c))
#define ON cout<<endl
#define PII pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const long long llinf = 0x3f3f3f3f3f3f3f3f;
////////////////////////////////////////Options//////////////////////////////////////////////////////
typedef long long ll;
#define stdcpph
#define CPP_IO

#ifdef stdcpph
#include<bits/stdc++.h>
#else
#include<ctype.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<algorithm>
#include<functional>
#ifdef CPP_IO
#include<iostream>
#include<iomanip>
#include<string>
#else
#include<stdio.h>
#endif
#endif
////////////////////////////////////////Basic Functions//////////////////////////////////////////////
template<typename INint>
inline void IN(INint &x)
{
	x = 0; int f = 1; char c; cin.get(c);
	while (c<'0' || c>'9') { if (c == '-')f = -1; cin.get(c); }
	while (c >= '0'&&c <= '9') { x = x * 10 + c - '0'; cin.get(c); }
	x *= f;
}
template<typename INint>
inline void OUT(INint x)
{
	if (x > 9)OUT(x / 10);
	cout.put(x % 10 + '0');
}
////////////////////////////////////////Added Functions//////////////////////////////////////////////
	//How to think:
	//先认真读题,把题目逻辑化,读清全部条件,再做,不然,哼哼
	//写题的时候遇到的一些”莫名“的错误大部分是自己的代码写错了一个变量
	//1.分治 2.容斥 3.化多元为单元
	//4.dp 分阶段,后阶段受前阶段的影响
	//5.凡是有很大的指数的,都可以先用log算一下
	//6.预处理,作用非常大,很快
	//
	//1.Do you use cout/cin? Do not use!
	//2.what's the maximum Int data? Is it beyond I32d?
	//3.Ever Mod after neccesary caEdlculation?
	//4.Ever Cleaned the array before using?
const int maxn = int(100);
const int maxm = 1e5 + 8;
const int mod = 1e9 + 7;
ll Add(ll a, ll b){
	ll c(a + b);
	return c >= mod ? c - mod : c;
}
ll Plus(ll a, ll b){
	ll c(a - b);
	return c < 0 ? c + mod : c;
}
ll Mul(ll a, ll b){
	ll c(a*b);
	return c % mod;
}

ll ans[maxn][maxn] = { 1 };//使用
ll cnt[maxn] = { 0 };
ll invcnt[maxn];
ll fac[maxm] = { 1 };
ll ans0;


ll dp[maxm] = { 1 };//使用全部物品,达到i
ll temp[maxm];
ll temp2[maxm];

string s;
ll len;
ll tonum(char c)
{
	if (c <= 'Z'&&c >= 'A')return c - 'A' + 1;
	else return c - 'a' + 1 + 26;
}

ll qpow(ll a, ll b, ll p)   //求a^bMODp
{
	ll ret = 1;
	while (b)
	{
		if (b & 1)
			ret = (ret * a) % p;
		a = (a * a) % p;
		b >>= 1;
	}
	return ret;
}
////////////////求逆元//////////////////////
////////费马小定理
ll inv(ll a, ll p)          //返回a对p的逆元
{
	return qpow(a, p - 2, p);
}
////////////////////////////////////////////Code/////////////////////////////////////////////////////
int main()
{
	//freopen("C:\\Users\\VULCAN\\Desktop\\data.in", "r", stdin);
	ll T(1), times(0);
#ifdef CPP_IO// CPP_IO
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	//cin >> T;
#else
	//IN(T);
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////
	while (++times, T--)
	{
		cin >> s; s = ' ' + s;
		len = s.length() - 1;
		RE2(i, s.length() - 1)
			++cnt[tonum(s[i])];
		RE2(i, 52)
		{
			if (!cnt[i])continue;
			for (ll j = len / 2; j >= cnt[i]; --j)
				dp[j] = Add(dp[j], dp[j - cnt[i]]);
		}
		RE2(i, 52)
			if (cnt[i])
			{
				ans[i][i] = dp[len / 2];
			}
		RE2(i, 52)
		{
			memcpy(temp, dp, sizeof(dp));
			//for (ll j = len / 2; j >= cnt[i]; --j)
			for (ll j = cnt[i]; j <= len / 2; ++j)
				temp[j] = Plus(temp[j], temp[j - cnt[i]]);
			for (ll j = i + 1; j <= 52; ++j)
			{
				memcpy(temp2, temp, sizeof(temp));
				//for (ll k = len / 2; k >= cnt[j]; --k)
				for (ll k = cnt[j]; k <= len / 2; ++k)
				{
					//temp2[k] -= temp2[k - cnt[j]];
					temp2[k] = Plus(temp2[k], temp2[k - cnt[j]]);
				}
				//ans[i][j] = ans[j][i] = temp2[len / 2 - cnt[i] - cnt[j]];
				ans[i][j] = ans[j][i] = Add(temp2[len / 2],temp2[len/2]);
			}
		}
		RE2(i, len)fac[i] = Mul(fac[i - 1], i); 
		ans0 = Mul(fac[len / 2], fac[len / 2]);
		RE2(i, 52)
		{
			//if (!cnt[i])continue;
			ans0 = Mul(ans0, inv(fac[cnt[i]], mod));
		}

		int q; cin >> q;
		RE2(i, q)
		{
			int l, r; cin >> l >> r;
			l = tonum(s[l]); r = tonum(s[r]);
			cout << ans[l][r]*ans0%mod << endl;
		}
	}
	/////////////////////////////////////////////////////////////////////////////////////////////////////
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41046771/article/details/86985900