河南省第九届ACM程序设计竞赛 部分题解

题目链接

A 表达式求值 <逆波兰>

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e3 + 10;
char str[N];

struct node
{
	ll v;
	char c;
	node &operator + (const node &o)
	{
		v += o.v;
		return *this;
	}
	node &operator * (const node &o)
	{
		v *= o.v;
		return *this;
	}
	void Smax(const node &o)
	{
		node t = o;
		ll a = 0, b = 0;
		while (v)
			a += v % 10, v /= 10;
		while (t.v)
			b += t.v % 10, t.v /= 10;
		v = max(a, b);
	}
};
inline int lv(char c)
{
	if (c == '+')
		return 2;
	if (c == '*')
		return 3;
	if (c == ',') //逗号最低
		return 1;
	return 0;
}
queue<node> q;
stack<node> stk;
void ToRPN(char *s)
{
	ll t = 0;
	for (int i = 0; s[i]; ++i)
	{
		if (isdigit(s[i]))
		{
			if (!i || !isdigit(s[i - 1]))
				t = s[i] - '0';
			else
				t = t * 10 + s[i] - '0';
			if (!isdigit(s[i + 1]))
				q.push({ t, 0 });
		}
		else if (s[i] == '(')
			stk.push({ 0, s[i] });
		else if (s[i] == ')')
		{
			while (stk.top().c != '(')
				q.push(stk.top()), stk.pop();
			stk.pop();
		}
		else if (!isalpha(s[i])) //不是Smax
		{
			while (!stk.empty() && lv(s[i]) < lv(stk.top().c))
				q.push(stk.top()), stk.pop();
			stk.push({ 0, s[i] });
		}
	}
	while (!stk.empty())
		q.push(stk.top()), stk.pop();
}
ll CalPRN()
{
	while (!q.empty())
	{
		char c = q.front().c;
		if (!c)
			stk.push(q.front()), q.pop();
		else
		{
			q.pop();
			node lst = stk.top();
			stk.pop();
			node fst = stk.top();
			stk.pop();
			if (c == '+')
				fst = fst + lst;
			else if (c == '*')
				fst = fst * lst;
			else if (c == ',')
				fst.Smax(lst);
			stk.push(fst);
		}
	}
	ll res = stk.top().v;
	stk.pop();
	return res;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		scanf("%s", str);
		ToRPN(str);
		printf("%lld\n", CalPRN());
	}

	return 0;
}

B 宣传墙 <状压dp> | <矩阵优化>

状态压缩,使一列四个砖块对应权值1 2 4 8,令d[i][j]表示第i列状态为j的方案数量,画图可以发现合法状态只有0 3 6 9 12 15,其它状态都不会出现。
然后手写每个状态的转移。。不使用矩阵优化也可以100ms飘过。

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 997;
template<typename T1, typename T2> inline bool setmin(T1 &a, const T2 &b){ if (b >= a) return false; a = b; return true; }
template<typename T1, typename T2> inline bool setmax(T1 &a, const T2 &b){ if (b <= a) return false; a = b; return true; }
template<typename T1, typename T2> inline void addmod(T1 &a, const T2 &b){ a = (a + b) % MOD; }

const int N = 1e6 + 10;
int f[N][16]; //第i列状态为j的方案数

int main()
{
#ifdef LOCAL
	//freopen("C:/input.txt", "r", stdin);
#endif
	f[1][0] = 1; //第1列为空
	for (int i = 1; i < N; ++i) //实际上合法状态只有0 3 6 9 12 15
	{
		addmod(f[i][0], f[i - 1][0] + f[i - 1][3] + f[i - 1][9] + f[i - 1][12] + f[i - 1][15]);
		addmod(f[i][3], f[i - 1][0] + f[i - 1][12]);
		addmod(f[i][6], f[i - 1][9]);
		addmod(f[i][9], f[i - 1][0] + f[i - 1][6]);
		addmod(f[i][12], f[i - 1][0] + f[i - 1][3]);
		addmod(f[i][15], f[i - 1][0]);
	}
	int T;
	cin >> T;
	while (T--)
	{
		int n, m, k, l, r;
		cin >> n >> m >> k;
		l = m - 1, r = n - (k + m - 1);
		printf("%d %d\n", f[l + 1][0], f[r + 1][0]); //输出下一列没溢出来的状态
	}

	return 0;
}

矩阵优化版1ms

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 997;
template<typename T1, typename T2> inline bool setmin(T1 &a, const T2 &b){ if (b >= a) return false; a = b; return true; }
template<typename T1, typename T2> inline bool setmax(T1 &a, const T2 &b){ if (b <= a) return false; a = b; return true; }
template<typename T1, typename T2> inline void addmod(T1 &a, const T2 &b){ a = (a + b) % MOD; }

struct Matrix
{
	int m[10][10];
	static const int N = 6; //阶数
	Matrix(int v = 0)
	{
		memset(m, 0, sizeof(m));
		if (v)
			for (int i = 0; i < N; i++)
				m[i][i] = v;
	}
	Matrix operator * (const Matrix &b)
	{
		Matrix t;
		for (int i = 0; i < N; i++)
			for (int j = 0; j < N; j++)
				for (int k = 0; k < N; k++)
					t.m[i][j] = (t.m[i][j] + m[i][k] * b.m[k][j]) % MOD;
		return t;
	}
	friend Matrix operator ^ (Matrix a, int n)
	{
		Matrix t(1);
		while (n)
		{
			if (n & 1)
				t = t * a;
			a = a * a;
			n >>= 1;
		}
		return t;
	}
}tran;
//下标0 1 2 3 4  5
//状态0 3 6 9 12 15
int main()
{
#ifdef LOCAL
	//freopen("C:/input.txt", "r", stdin);
#endif
	tran.m[0][0] = tran.m[1][0] = tran.m[3][0] = tran.m[4][0] = tran.m[5][0] = 1;
	tran.m[0][1] = tran.m[4][1] = 1;
	tran.m[3][2] = 1;
	tran.m[0][3] = tran.m[2][3] = 1;
	tran.m[0][4] = tran.m[1][4] = 1;
	tran.m[0][5] = 1;
	int T;
	cin >> T;
	while (T--)
	{
		int n, m, k, l, r;
		cin >> n >> m >> k;
		l = m - 1, r = n - (k + m - 1);
		Matrix a, b; //a[0][i]表示当前列状态为i的方案数
		a.m[0][0] = b.m[0][0] = 1; //1列状态为0
		a = a * (tran ^ l); //得到l+1项的0状态
		b = b * (tran ^ r);
		printf("%d %d\n", a.m[0][0], b.m[0][0]);
	}

	return 0;
}

C 信道安全

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e4 + 10;
int n, m;

struct node
{
	int v;
	double p;
	bool operator < (const node &o) const
	{
		return p < o.p;
	}
};
vector<node> e[N];
double dis[N];
bool vis[N];

void dijkstra()
{
	memset(dis, 0, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	priority_queue<node> pq;
	pq.push({ 1, 1 });
	dis[1] = 1;
	while (!pq.empty())
	{
		int u = pq.top().v; pq.pop();
		vis[u] = 1;
		for (auto it : e[u])
		{
			int v = it.v;
			double p = it.p;
			if (!vis[v] && dis[v] < dis[u] * p)
				dis[v] = dis[u] * p, pq.push({ v, dis[v] });
		}
	}
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		cin >> n >> m;
		for (int i = 1; i <= n; ++i)
			e[i].clear();
		for (int i = 0; i < m; ++i)
		{
			int u, v;
			double p;
			scanf("%d%d%lf", &u, &v, &p);
			e[u].push_back({ v, p / 100 });
			e[v].push_back({ u, p / 100 });
		}
		dijkstra();
		printf("%.6f\n", dis[n] * 100);
	}

	return 0;
}

E 机器设备 <搜索>

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 2e3 + 10;
int x[N], y[N], r[N];
vector<int> e[N];
int n, X, Y, st, ed;
double ans = 0, S;

bool DFS(int x, int f)
{
	if (x == ed)
	{
		ans += S / r[x];
		return true;
	}
	for (int y : e[x]) if (y != f)
		if (DFS(y, x))
		{
			ans += S / r[x];
			return true;
		}
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		cin >> n >> X >> Y;
		for (int i = 1; i <= n; ++i)
		{
			scanf("%d%d%d", &x[i], &y[i], &r[i]);
			if (x[i] == 0 && y[i] == 0)
				st = i;
			else if (x[i] == X && y[i] == Y)
				ed = i;
			e[i].clear();
		}
		S = r[st] * 10000;
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j < i; ++j)
				if ((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) == (r[i] + r[j]) * (r[i] + r[j]))
					e[i].push_back(j), e[j].push_back(i);
		ans = 0;
		DFS(st, 0);
		printf("%d\n", (int)(ans + 1e-6));
	}

	return 0;
}

F Decimal integer conversion <暴力>

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		string a, b;
		cin >> a >> b;
		set<ll> st;
		for (int i = 0; i < a.size(); ++i) //位置
			for (int j = 0; j < 2; ++j)
			{
				string c = a;
				c[i] = j + '0';
				if (c != a)
					st.insert(stoll(c, 0, 2));
			}
		for (int i = 0; i < b.size(); ++i) //位置
			for (int j = 0; j < 3; ++j)
			{
				string c = b;
				c[i] = j + '0';
				if (c != b)
				{
					ll res = stoll(c, 0, 3);
					if (st.find(res) != st.end())
					{
						cout << res << endl;
						goto brk;
					}
				}
			}
brk:	continue;
	}

	return 0;
}

G Prototypes analyze <模拟>

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
struct node
{
    int v;
    node *l, *r;
}t[100];
void Insert(node *f, int v)
{
    if (v < f->v)
    {
        if (f->l)
            Insert(f->l, v);
        else
            f->l = new node{ v, 0, 0 };
    }
    else
    {
        if (f->r)
            Insert(f->r, v);
        else
            f->r = new node{ v, 0, 0 };
    }
}
bool equal(node *a, node *b)
{
    if (!a && !b)
        return true;
    if (!a && b || a && !b)
        return false;
    if (a->l && !equal(a->l, b->l))
        return false;
    if (a->r && !equal(a->r, b->r))
        return false;
    return true;
}
int main()
{
#ifdef LOCAL
    freopen("C:/input.txt", "r", stdin);
#endif
    int T;
    cin >> T;
    while (T--)
    {
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i)
        {
            int x;
            scanf("%d", &x);
            t[i] = { x, 0, 0 };
            for (int j = 1; j < m; ++j)
            {
                int x;
                scanf("%d", &x);
                Insert(&t[i], x);
            }
        }
        int k = 0;
        for (int i = 1; i <= n; ++i)
        {
            int flag = 1;
            for (int j = 1; j < i; ++j)
                if (equal(&t[i], &t[j]))
                    flag = 0;
            if (flag)
                ++k;
        }
        cout << k << endl;
    }
    return 0;
}

你可能感兴趣的:(_动态规划_,___图论___,搜索,_数据结构_,矩阵优化,dijkstra,暴力枚举,模拟,状压dp)