2018NOIP 模拟题

T1

2018NOIP 模拟题_第1张图片
2018NOIP 模拟题_第2张图片

分析

一道水题。当a大于b的时候,我们选择串联一个电容器,于是就转化成了c1 +1 = a/b。
当b大于a的时候,我们选择并联一个电容器,于是就有c1/c1+1 = a/b。

代码

#include
#include
#include
using namespace std;

typedef long long ll;
int T;
ll a, b, ans;

ll gcd(ll x, ll y)
{
	if(y == 0) return x;
	else return gcd(y, x%y);
}

int main()
{
//	freopen("capacitor.in","r",stdin);
//	freopen("capacitor.out","w",stdout);
	scanf("%d", &T);
	while(T--)
	{
		ans = 0;
		scanf("%lld%lld", &a, &b);
		if(a == 1)
		{
			printf("%lld\n", b);
			continue;
		}
		if(b == 1)
		{
			printf("%lld\n", a);
			continue;
		}
		ll Gcd = gcd(a, b);
		a /= Gcd;
		b /= Gcd;
		while(a != 1 && b != 1)
		{
			if(a > b)
			{
				ans ++;
				a = a - b;
			}
			if(b > a)
			{
				ans++;
				b = b - a;
			}
		}
		if(a == 1) ans += b;
		else ans += a;
		printf("%lld\n", ans);
	}
	return 0;
}

T2 到不了

2018NOIP 模拟题_第3张图片
2018NOIP 模拟题_第4张图片

分析

这道题并没有要求在线处理,所以我们先用并查集维护一下,就可以建出一棵最后的树,
然后再预处理Lca。
再扫一遍操作,同样用并查集维护每个点这个时候的根,就可以直接求lca了。

T3 Track

2018NOIP 模拟题_第5张图片
2018NOIP 模拟题_第6张图片

分析

这道题一开始我感觉是用Kmp,后来我用了DFS写,但是犯了一个错误,就是假设我们跑到第i个节点,与Tom的路线不再匹配,我们不必要回到第0步重新匹配。
我们设f[i][j][k]为跑到第i秒,高度为j,成功匹配k个字母的方案数。
这道题我们可以用KMP预处理一下。特别注意我们用Fail[i][0/1]表示用D/U匹配失败后可以满足的前缀长度。

#include
#include
#include
#include
using namespace std;

const int MAXN = 205, MOD = 1e9+7;
int T, Len;
char s[MAXN];
int Next[MAXN], Fail[MAXN][2], f[MAXN][MAXN][MAXN];

void Get()
{
   int j = 0;
   Next[0] = Next[1] = 0;
   for(int i = 1; i < Len; i++)
   {
   	while(j>0 && s[i]!=s[j]) j = Next[j];
   	if(s[i] == s[j]) j++;
   	Next[i+1] = j;
   }
   Fail[0][s[0]=='U'] = 1;
//	if(s[0] == 'U') Fail[0][1] = 1;
//	else Fail[0][0] = 1;
   for(int i = 1; i <= Len; i++)
   {
   	int Pos = i;
   	while(Pos && s[Pos]!='U') Pos = Next[Pos];
   	Fail[i][1] = Pos+1;
   	if(Pos==0 && s[0]=='D') Fail[i][1] = 0;
   	Pos = i;
   	while(Pos && s[Pos] != 'D') Pos = Next[Pos];
   	Fail[i][0] = Pos+1;
   	if(Pos==0 && s[0]=='U') Fail[i][0] = 0;
   }
   return;
}

int main()
{
   cin >> T;
//	scanf("%d", &T);
   scanf("%s", s);
   Len = strlen(s);
   if(T%2 != 0)
   {
   	printf("0\n");
   	return 0;
   }
   Get();
   f[0][0][0] = 1;
   for(int i = 0;i < T; i++)
   {
   	for(int j = 0; j <= min(i, T-i); j++)
   	{
   		for(int k = 0; k < Len; k++)
   		{
   			if(s[k] == 'U')
   			{
   				f[i+1][j+1][k+1] = (f[i+1][j+1][k+1] + f[i][j][k]) % MOD;
   				if(j) (f[i+1][j-1][Fail[k][0]]+=f[i][j][k])%=MOD;
   			} else {
   				(f[i+1][j+1][Fail[k][1]] += f[i][j][k]) %= MOD;
   				if(j) (f[i+1][j-1][k+1]+=f[i][j][k]) %= MOD;
   			}
   		}
   		(f[i+1][j+1][Len]+=f[i][j][Len]) %= MOD;
   		if(j) (f[i+1][j-1][Len]+=f[i][j][Len]) %= MOD;
   	}
   }
   printf("%d\n", f[T][0][Len]);
   return 0;
}

你可能感兴趣的:(2018NOIP 模拟题)