2018NOIP 模拟题
T1
分析
一道水题。当a大于b的时候,我们选择串联一个电容器,于是就转化成了c1 +1 = a/b。
当b大于a的时候,我们选择并联一个电容器,于是就有c1/c1+1 = a/b。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
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 到不了
分析
这道题并没有要求在线处理,所以我们先用并查集维护一下,就可以建出一棵最后的树,
然后再预处理Lca。
再扫一遍操作,同样用并查集维护每个点这个时候的根,就可以直接求lca了。
T3 Track
分析
这道题一开始我感觉是用Kmp,后来我用了DFS写,但是犯了一个错误,就是假设我们跑到第i个节点,与Tom的路线不再匹配,我们不必要回到第0步重新匹配。
我们设f[i][j][k]为跑到第i秒,高度为j,成功匹配k个字母的方案数。
这道题我们可以用KMP预处理一下。特别注意我们用Fail[i][0/1]表示用D/U匹配失败后可以满足的前缀长度。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
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;
}