【LGR-199-Div.3】复旦勰码基础赛 #16 & FSLOI Round 1

Natural-TLP / 2024-09-23 / 原文

P11076 「FSLOI Round I」单挑

思路

最多连续胜利的场数最少是多少,其实就是在剩余的S里面插入F的连续胜场的最大值是多,以为要先小S获胜,可以插入的空的数量就是剩余S的大小,平均值上取整就是答案。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iomanip>
#include <numeric>
#include <unordered_map>
#include <unordered_set>

#define endl        '\n'
#define ll          long long
#define PII         pair<int, int> 
#define PLL         pair<ll, ll>
#define all(a)      a.begin(), a.end()
#define lowbit(x)   x & -x
#define ent         cout << '\n'
#define out(x)      cout << x << ' '
#define out2(x, y)  cout << x << " ~ " << y << ' '
#define me(a, b)    memset(a, b, sizeof a)
#define mc(a, b)    memcpy(a, b, sizeof a)
#define pk          push_back
#define ur(x)       sort(all(x)), x.erase(unique(all(x)), x.end())
#define fi          first
#define se          second
#define si(x)       int(x.size())
#define chi(x)      (x - '0')
#define ull         unsigned long long
#define Mp          make_pair

using namespace std;

const ll inf = 1e18;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
const int mod = 998244353;
const int P = 1e9 + 7;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {-1, 1, 0, 0};
const int N = 1e6 + 10;
const int M = 1000 + 10;

int n, x, y;

void solve()
{
  cin >> n >> x >> y;
  
  string s; 
  cin >> s;
  
  for (int i = 0; i < si(s); i ++)
  	if (s[i] == 'F') x --;
  	else y --;

  cout << (x + y - 1) / y << "\n";
}

int main()
{
  ios::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);

  int t = 1;
  cin >> t;

  while (t --) solve();

  return 0;
}

P11077 「FSLOI Round I」石子

思路

不可行的情况明显是对于一个不等于平均值的数,无论如何加减k值都不可能到达平均值。
接下讨论可行情况的胜负,明显的对于一个不等于平均值的数,可以进行的操作数是(平均值-它)/k,因为是同时操作两个数,所以最后总操作数要除以2,所以操作数是奇数的话先手必胜,偶数后手必胜。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iomanip>
#include <numeric>
#include <unordered_map>
#include <unordered_set>

#define endl        '\n'
#define ll          long long
#define PII         pair<int, int> 
#define PLL         pair<ll, ll>
#define all(a)      a.begin(), a.end()
#define lowbit(x)   x & -x
#define ent         cout << '\n'
#define out(x)      cout << x << ' '
#define out2(x, y)  cout << x << " ~ " << y << ' '
#define me(a, b)    memset(a, b, sizeof a)
#define mc(a, b)    memcpy(a, b, sizeof a)
#define pk          push_back
#define ur(x)       sort(all(x)), x.erase(unique(all(x)), x.end())
#define fi          first
#define se          second
#define si(x)       int(x.size())
#define chi(x)      (x - '0')
#define ull         unsigned long long
#define Mp          make_pair

using namespace std;

const ll inf = 1e18;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
const int mod = 998244353;
const int P = 1e9 + 7;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {-1, 1, 0, 0};
const int N = 1e6 + 10;
const int M = 1000 + 10;

int n, k;
ll a[N];

void solve()
{
	cin >> n >> k;
	ll sum = 0;
	for (int i = 1; i <= n; i ++) cin >> a[i], sum += a[i];

	ll ave = sum / n;
	bool flag = 0;
	ll cnt = 0;
	for (int i = 1; i <= n; i ++)
	{
		int num = abs(a[i] - ave);
		if (num % k) {
			flag = 1;
			break;
		}
		else {
			cnt = cnt + num / k;
		}
	}
	
	if (flag) {
		cout << "Draw" << '\n';
		return ;
	}
	
	cnt = (cnt + 1) / 2;
	
	if (cnt % 2) cout << 'F' << '\n';
	else cout << "L" << '\n';
}

int main()
{
  ios::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);

  int t = 1;
  cin >> t;

  while (t --) solve();

  return 0;
}

P11078 「FSLOI Round I」迷雾

思路

明显按照题意模拟必定超时,但观察发现对于同一个移动进行偶数次操作是不变的,所以考虑用差分,当进入一个迷雾时将所有要操操作的移动进行一次标记就是:\(C_{i+k}+1,C_{i+b_{i}*k + k}-1\),因为只有间隔k的数进行差分,前缀和的时候也只从间隔为k的数转移过来。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iomanip>
#include <numeric>
#include <unordered_map>
#include <unordered_set>

#define endl        '\n'
#define ll          long long
#define PII         pair<int, int> 
#define PLL         pair<ll, ll>
#define all(a)      a.begin(), a.end()
#define lowbit(x)   x & -x
#define ent         cout << '\n'
#define out(x)      cout << x << ' '
#define out2(x, y)  cout << x << " ~ " << y << ' '
#define me(a, b)    memset(a, b, sizeof a)
#define mc(a, b)    memcpy(a, b, sizeof a)
#define pk          push_back
#define ur(x)       sort(all(x)), x.erase(unique(all(x)), x.end())
#define fi          first
#define se          second
#define si(x)       int(x.size())
#define chi(x)      (x - '0')
#define ull         unsigned long long
#define Mp          make_pair

using namespace std;

const ll inf = 1e18;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
const int mod = 998244353;
const int P = 1e9 + 7;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {-1, 1, 0, 0};
const int N = 1e6 + 10;
const int M = 1000 + 10;

int n, m, k, q;
int cc[N];
char g[M][M];
struct node {
	char op;
	int a, b;
} o[N];

void dfs(int x, int y, int step)
{
	if (step > q) {
		cout << x << ' ' << y << '\n';
		return ;
	}
	
    // 前缀和,注意要进行前缀的数组,安间隔k分组
	cc[step] += cc[step - k];
	
	char op = o[step].op;
	int a = o[step].a;
	
    // 偶数次操作是不变,这里判断奇数次时改变移动方向
	if (cc[step] % 2) {
		if (op == 'U') op = 'D';
		else if (op == 'D') op = 'U';
		else if (op == 'L') op = 'R';
		else op = 'L';
	}
	
	if (op == 'U') {
		x -= a;
		if (x < 1) x = 1;
	}
	else if (op == 'D') {
		x += a;
		if (x > n) x = n;
	}
	else if (op == 'L') {
		y -= a;
		if (y < 1) y = 1;
	}
	else {
		y += a;
		if (y > m) y = m;
	}
	
	if (g[x][y] == 'X') {
		if (o[step].b > 0) {
            // 差分
			int l = k + step, r = k * o[step].b + step;
			cc[l] ++;
			cc[r + k] --;
		}
	}
	dfs(x, y, step + 1);
}

void solve()
{
  cin >> n >> m >> q >> k;
  
  for (int i = 1; i <= n; i ++)
  	for (int j = 1; j <= m; j ++)
  		cin >> g[i][j];
  		
  for (int i = 1; i <= q; i ++)
  	cin >> o[i].op >> o[i].a >> o[i].b;
  	
  dfs(1, 1, 1);
}

int main()
{
  ios::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);

  int t = 1;
  // cin >> t;

  while (t --) solve();

  return 0;
}

P11079 「FSLOI Round I」山峦

不会,看下官方题解吧

贴一份官方题解的代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int n,a[510],f1[510][510]={0},f2[510][510]={0},dp[510]={0};
int sum[1000010];
int solve(int l,int r){
	int ans=0;
	for(int i=l+1;i<=r-1;i++){
		if(f1[l][i]&&f2[r][i]) ans=(ans+f1[l][i]*f2[r][i]%mod-1+mod)%mod;
		ans=(ans+sum[a[i]]*f2[r][i]%mod)%mod;
		sum[a[i]]=(sum[a[i]]+f1[l][i])%mod;
	}
	for(int i=l+1;i<=r-1;i++) sum[a[i]]=0;
	return ans;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		f1[i][i]=1;
		for(int j=i+1;j<=n;j++){
			for(int k=i;k<=j-1;k++){
				if(a[k]>a[j]) f1[i][j]=(f1[i][j]+f1[i][k])%mod;
			}
		}
	}
	for(int i=n;i>=1;i--){
		f2[i][i]=1;
		for(int j=i-1;j>=1;j--){
			for(int k=j+1;k<=i;k++){
				if(a[k]>a[j]) f2[i][j]=(f2[i][j]+f2[i][k])%mod;
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i-1;j++) dp[i]=(dp[i]+f2[i][j])%mod;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i-3;j++){
			if(a[j]>=a[i]) continue;
			dp[i]=(dp[i]+dp[j]*solve(j,i)%mod)%mod;
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		int Sum=0;
		for(int j=i+1;j<=n;j++) Sum=(Sum+f1[i][j])%mod;
		ans=(ans+Sum*dp[i]%mod)%mod;
	}
	cout<<ans<<endl;
	return 0;
}