2024.11.22

今日总结
上午打模拟赛,下午改完了三道题+半道题,最后一题只会到27分的做法,其他的看不懂晚上做了两年NOIP其中的真题
1:集邮比赛3
这道题是一道很显然的区间Dp题目

点击查看代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N = 210;
const int INF = 1e18;

int n,L,ans;
int x[N],t[N],dp[N][N][N][3];

signed main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%lld%lld",&n,&L);
    for(int i = 1;i <= n;i ++)
        scanf("%lld",&x[i]);
    for(int i = 1;i <= n;i ++)
        scanf("%lld",&t[i]);
    memset(dp,0x3f,sizeof(dp));
    x[n + 1] = L;
    dp[0][0][0][0] = dp[0][0][0][1] = 0;
    for(int l = 0;l <= n;l ++)
    {
        for(int r = 0;r <= n;r ++)
        {
            if(l + r >= n) break;
            for(int k = 0;k <= n;k ++)
            {
                if(dp[l][r][k][0] <= INF)
                {
                    dp[l + 1][r][k + (dp[l][r][k][0] + x[n - l + 1] - x[n - l] <= t[n - l])][0] = min(dp[l + 1][r][k + (dp[l][r][k][0] + x[n - l + 1] - x[n - l] <= t[n - l])][0],dp[l][r][k][0] + x[n - l + 1] - x[n - l]);
					dp[l][r + 1][k + (dp[l][r][k][0] + L - x[n - l + 1] + x[r + 1] <= t[r + 1])][1] = min(dp[l][r + 1][k + (dp[l][r][k][0] + L-x[n - l + 1] + x[r + 1] <= t[r + 1])][1],dp[l][r][k][0] + L - x[n - l + 1] + x[r + 1]);
                }
                if(dp[l][r][k][1] <= INF)
                {
                    dp[l + 1][r][k + (dp[l][r][k][1] + L - x[n - l] + x[r] <= t[n - l])][0]=min(dp[l + 1][r][k + (dp[l][r][k][1] + L - x[n - l] + x[r] <= t[n - l])][0],dp[l][r][k][1] + L - x[n - l] + x[r]);
					dp[l][r + 1][k + (dp[l][r][k][1] + x[r + 1] - x[r] <= t[r + 1])][1] = min(dp[l][r + 1][k + (dp[l][r][k][1] + x[r + 1] - x[r] <= t[r + 1])][1],dp[l][r][k][1] + x[r + 1] - x[r]);
                }
            }
        }
    }
    for(int l = 0;l <= n;l ++)
        for(int r = 0;r <= n;r ++)
            for(int k = 0;k <= n;k ++)
                if(min(dp[l][r][k][0],dp[l][r][k][1]) < INF) ans = max(ans,k);
    printf("%lld\n",ans);
    return 0;
}

2:不允許打手槍
这道题是一道需要分类讨论的状态机Dp的题目,只需要处理好每个点可以进行的状态,在进行转移,用滚动数组优化一下,但一定还要对范围进行优化,否则会TLE最后几个点,不要尝试写O(1e9)复杂度的代码,一定会被卡

点击查看代码
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 46,K = 91;
const int Mod = 998244353;

int n,m,k;
int a[N][N],b[N][N];
int dp[3][N][N][N][K];

void Clear(int i,int fa)
{
    for(int j = 1;j <= m;j ++)
        for(int L = 0;L <= n - i;L ++)
            for(int Z = 0;Z <= m - j;Z ++)
                for(int p = 0;p <= k;p ++)
                    dp[fa][j][L][Z][p] = 0;
}

int main()
{
    freopen("railway.in","r",stdin);
    freopen("railway.out","w",stdout);
    function<int(int,int)>add = [&](int x,int y)
    {
        long long p = (long long)x + (long long)y;
        if(p >= Mod) p -= Mod;
        return (int)p;
    };
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= m;j ++)
            scanf("%d",&a[i][j]);
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= m;j ++)
            scanf("%d",&b[i][j]);
    dp[1][1][0][0][k] = 1;
    int u = 1,fa = 0;
    for(int i = 1;i <= n;i ++)
    {
        for(int j = 1;j <= m;j ++)
        {
            for(int L = 0;L <= n - i;L ++)
            {
                for(int Z = 0;Z <= m - j;Z ++)
                {
                    for(int p = 0;p <= k;p ++)
                    {
                        if(i > 1) dp[u][j][L][Z][p] = add(dp[u][j][L][Z][p],dp[fa][j][L + 1][Z][p]) ; // 用L
                        if(j > 1) dp[u][j][L][Z][p] = add(dp[u][j][L][Z][p],dp[u][j - 1][L][Z + 1][p]) ; // 用Z
                        if(L > 0 && Z > 0 && p + a[i][j] + b[i][j] <= k) dp[u][j][L][Z][p] = add(dp[u][j][L][Z][p],(Mod - dp[u][j][L - 1][Z - 1][p + a[i][j] + b[i][j]])); // 买L和Z
                        if(L > 0 && p + a[i][j] <= k) dp[u][j][L][Z][p] = add(dp[u][j][L][Z][p],dp[u][j][L - 1][Z][p + a[i][j]]) ; // 买L
                        if(Z > 0 && p + b[i][j] <= k) dp[u][j][L][Z][p] = add(dp[u][j][L][Z][p],dp[u][j][L][Z - 1][p + b[i][j]]); // 买Z
                    }
                }
            }
            printf("%lld ",dp[u][j][0][0][0]);
        }
        printf("\n");
        Clear(i,fa);
        u ^= 1,fa ^= 1;
    }
    return 0;
}

3:我們學生躲在遊戲屋,不覺得羞愧?
一旦看到这种新定义的题目,不要以为是很难的数学知识,先简单的推一推,也有可能是需要对式子进行找规律进行if判断就能推出来

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define int long long

int T,n,k;

void read(int &v)
{
	v = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9')
		ch = getchar();
	while(ch >= '0' && ch <= '9')
	{
		v = v * 10 + ch - 48;
		ch = getchar();
	}
}

int work()
{
	if(k == 1) return 0;
	int ans = 0;
	if(k >= 4)
	{
		++ ans;
		if(n > 2) ans += n - 2;
	}
	if(n >= 2)
	{
		if(k >= 5) ++ ans;
		if(k >= 4) ++ ans;
	}
	if(k >= 4) if(n > 3) ans += n - 3;
	if(k >= 5 && n >= 3) ++ ans;
	if(k == 2) ++ ans;
	return ans;
}

void write(int x)
{
	if(x < 10)
	{
		putchar(x + '0');
		return;
	}
	write(x / 10);
	putchar(x % 10 + '0');
}

signed main()
{
	freopen("set.in","r",stdin);
	freopen("set.out","w",stdout);
	scanf("%d",&T);
	while(T --)
	{
		read(n),read(k);
		write(work());
		putchar('\n');
	}
	return 0;
}

4:傳自我的手機
这道题正解应该是要用到线段树合并和并查集,我只写了一个用并查集的暴力解法

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N = 5e3 + 10;
const int M = N * 2;

int c,n,q,u,v,opt,x,y,tot;
int a[M],bel[M],vis[M],gx[M];
int ans[M],f[M];
set<int> s[M];

int Find(int x) 
{
	if(x == f[x]) return x;
	return f[x] = Find(f[x]);
}

void dfs(int x,int fa) 
{
	if(vis[x]) return;
	vis[x] = tot;
	for(auto y : s[x]) 
		if(y != fa) dfs(y,x);
}

signed main() 
{
	freopen("component.in", "r", stdin);
	freopen("component.out", "w", stdout);
    scanf("%lld%lld%lld%lld%ld",&c,&n,&q,&u,&v);
	int Mod = pow(u,v);
	for(int i = 1;i <= n;i ++) scanf("%lld",&a[i]);
	if(c <= 3)
    {
		for(int i = 1;i <= q;i ++) 
        {
			scanf("%lld",&opt);
			if(opt == 1) 
            {
                scanf("%d%d",&x,&y);
				s[x].insert(y),s[y].insert(x);
			} 
            else if(opt == 2) 
            {
                scanf("%d%d",&x,&y);
				s[x].erase(y),s[y].erase(x);
			} 
            else if(opt == 3) 
            {
				scanf("%d%d",&x,&y);
				a[x] = y;
			} 
            else 
            {
				scanf("%d",&x);
				tot = 0;
				memset(vis,0,sizeof(vis));
				for(int i = 1;i <= n;i ++) 
                {
					if(!vis[i]) 
                    {
						tot ++;
						dfs(i,0);
					}
				}
				for(int i = 1;i <= tot;i ++)
					gx[i] = 1;
				for(int i = 1;i <= n;i ++) 
                {
					gx[vis[i]] *= a[i] + x;
					gx[vis[i]] %= Mod;
				}
				int ans = 0;
				for(int i = 1;i <= tot;i ++) 
                {
					ans += gx[i];
					ans %= Mod;
				}
                printf("%lld\n",ans);
			}
		}
	}
	if(c == 4) 
    {
		int ret = 0;
		for(int i = 1;i <= n;i ++) 
        {
			f[i] = i;
			ans[i] = a[i];
			ret += a[i];
			ret %= Mod;
		}
		for(int i = 1;i <= q;i ++) 
        {
            scanf("%lld",&x);
			if(opt == 1) 
            {
                scanf("%lld%lld",&x,&y);
				int fx = Find(x),fy = Find(y);
				if(fx != fy) 
                {
					f[fx] = fy;
					ret -= ans[fx];
					ret -= ans[fy];
					ans[fy] = ans[fx] * ans[fy] % Mod;
					ret += ans[fy];
					ret = (ret % Mod + Mod) % Mod;
					ans[fx] = 0;
				}
			} 
            else if(opt == 2 || opt == 3) scanf("%lld%lld",&x,&y);
			else
            {
                scanf("%lld",&x);
				printf("%lld\n",ret);
			}
		}
	}
    return 0;
}

5:幂次
这道题与今天考试的第三题类型相同,都是需要推一推公式进行判断就能出来结果

点击查看代码
#include<bits/stdc++.h>

using namespace std;

#define int long long

const int N = 110;
const long double eps = 1e-18;

int n,k,ans = 1;
int f[N];

signed main()
{
    scanf("%lld%lld",&n,&k);
    for(int i = 100;i >= k;i --)
    {
        f[i] = pow<long double>(n,1.0 / i) + eps - 1;
        for(int j = i << 1;j <= 100;j += i) f[i] -= f[j];
        ans += f[i];
    }
    printf("%lld\n",ans);
    return 0;
}

6:种花
这道题其实是一道模拟+前缀和的题目,但这道题难的是需要在前缀和上求前缀和,很新颖,并且在遍历的同时,记录前缀和,思路很好想,但是在写代码的时候细节很多,需要维护的东西很多,尤其是加上了横纵坐标

点击查看代码
#include<bits/stdc++.h>

using namespace std;

const int N = 1e3 + 10;
const int Mod = 998244353;

int n,m,c,f,C,F,jil,jis,jilf;
int s[N][N];
char mp[N][N];

int main()
{
    // freopen("plant.in","r",stdin);
    // freopen("plant.out","w",stdout);
    int T,id;
    scanf("%d%d",&T,&id);
    while(T --)
    {
        memset(s,0,sizeof(s));
        scanf("%d%d%d%d",&n,&m,&c,&f);
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= m;j ++)
                cin >> mp[i][j];
        for(int i = 1;i <= n;i ++)
        {
            for(int j = m - 1;j >= 1;j --)
            {
                if(mp[i][j] == '1') s[i][j] = -1;
                else if(mp[i][j + 1] == '0') s[i][j] = s[i][j + 1] + 1;
            }
        }
        for(int j = 1;j < m;j ++)
        {
            jil = jilf = 0;
            for(int i = 1;i <= n;i ++)
            {
                if(s[i][j] == -1)
                {
                    jil = jilf = 0;
                    continue;
                }
                // cout << "jil:" << jil << endl;
                C = C % Mod + (1ll * s[i][j] * (jil % Mod)) % Mod; // s[i][j] * jil
                // cout << "C:" << C << endl;
                F = (F % Mod + jilf % Mod) % Mod;
                // cout << "jilf:" << jilf << endl;
                // cout << "F:" << F << endl;
                jilf = (jilf + (1ll * s[i][j] * (jil % Mod)) % Mod) % Mod;
                jil += max(0,s[i - 1][j]);
            }
        }
        printf("%d %d\n",(c * C) % Mod,(f * F) % Mod);
        C = F = 0;
    }
    return 0;
}
posted @ 2024-11-23 06:19  Kevinhwbb  阅读(11)  评论(0编辑  收藏  举报