zoukankan      html  css  js  c++  java
  • 【2020-10-1 模拟赛】

    今年悲催的在外过国庆 + 中秋
    100 + 82 + 70 + 2 = 257
    全场Rk8(我太菜辽)

    A

    回家 (home)
    1.1 题目描述
    一只袋鼠在数轴上。0 时刻,袋鼠位于 0 处。在时刻 i−1 和 i 之间的时间段中,
    袋鼠要么待在当前位置,要么向左或向右跳恰好 i 单位长度。也就是说,如果时
    刻 i − 1 时它在 x 位置,那么时刻 i 时它可能的位置是 x − i、x 或 x + i。袋鼠
    的家在 X 位置处,它想尽快从 0 走到 X。求袋鼠最早在哪个时刻可以到达 X。
    1.2 输入格式
    一行一个整数 X。
    1.3 输出格式
    一个整数,表示袋鼠最早在哪个时刻可以到达 X。

    算法

    签到题
    这题等价于把1~n这个区间分成k个子区间
    其中(k_1 < k_2 < k_3 < k_4······<k_i)
    k_i就是我们的答案
    比赛的时候用的二分 检验一个mid 如果(1 + 2 + 3 + ······ + mid < n)

    代码

    #include<iostream>
    #include<cstdio>
    #include<map>
    #define ll long long
    using namespace std;
    ll n;
    ll l,r;
    bool cheek(ll num)
    {
        ll ans = 0;
        for(ll i = num;i >= 1;i--)
        {
        	ans += i;
        	if(ans >= n)
        	return true;
    	}
    	return false;
    }
    int main()
    {
    	freopen("home.in","r",stdin);
    	freopen("home.out","w",stdout);
    	scanf("%lld",&n);
    	l = 1,r = n;
    	while(l <= r)
    	{
    		ll mid = (l + r)>>1;
    		if(cheek(mid))
    		r = mid;
    		else
    		l = mid + 1;
    		if(l == r)
    		break;
    	}
    	cout<<r;
    }
    
    

    B

    不必要 不必要 (unnecessary)
    2.1 题目描述
    小 A 有 N 张写有正整数的牌,第 i 张牌上的数是 a i (1 ≤ i ≤ N) 。因为他很
    喜欢大的数,所以他认为一个卡牌的子集是“好”的,当且仅当该子集中的卡
    牌上的数之和大于等于 K(卡牌上的数可以相同) 。
    接下来,他会判断每张牌 i 是否是“不必要”的,判断方法如下:
    • 如果所有包含 i 的“好”的子集去掉 i 后仍然是“好”的,那么 i 是“不
    必要”的。
    • 否则,i 不是“不必要”的。
    请你求出“不必要”的牌的张数。
    注意:每张牌的判断是独立的,并且他不会扔掉那些被判断为“不必要”的牌。
    2.2 输入格式
    第一行,两个正整数 N,K。
    第二行,N 个正整数 a i 。
    2.3 输出格式
    一个数, “不必要”的牌的张数。

    心路历程

    刚开始看到这道题
    大概10min码完了
    然后因为题目样例给的太水
    我的错误想法水过了全部的样例
    我的想法是先把所有元素排序 然后对最后这个数组进行子序列的算法 让每个子序列(a_i < a_{i+1} < a_{i+2} < ······ < a_j) 其中

    (left{ egin{array}{**lr**} a_{i} + a_{i+1} + a_{i+2} + a_{i+3} ······ + a_j geq k\ a_{i+1} + a_{i+2} + a_{i+3} ······ + a_j < k end{array} ight.)

    维护这些子序列的并的元素的数量为cnt
    最后输出 n - cnt
    这样明显是错的
    没有考虑到所有的子集
    这里提供一组bug数据
    stdin:
    5 13
    2 2 2 2 9
    stdout:
    0
    但是这个错误程序跑了82分 真怀疑数据用脚造的
    最后十分钟发现了这个错误但还是无力回天了
    难过

    算法

    暴力的算法就不考虑了

    算法一:

    我们记(f_i[s],g_i[s])分别表示(1~i,i~N)是否存在和为s的子集
    然后枚举每张牌(i),用(f_{i - 1} 、g_{i + 1})判断是否存在和为([K-a_i,K))的子集。
    如果存在 那么这张牌(i)是必要的
    我们最后减去所有必要的牌就是答案
    时间复杂度: (O(NK))

    算法二:

    我们考虑优化算法一:
    对于(a_igeq a_j) 如果(a_j)是不必要的 那么(a_i)也是不必要的
    将a从小到大排序 那么“不必要”的一定是一段前缀和
    我们从后往前加入每个元素 我们考虑我们现在加入到第(i + 1 ~ N) 此时 考虑 有(p_{i + 1} 个不必要的牌)
    考虑加入(i)如何计算(p_i)
    先考虑i是否是只考虑(i ~ N)时不必要的牌
    我们只需要判断(i + 1 ~ N)(< K)的子集和的最大值是否大于(geq K - a_i)
    (s_i)表示(i ~ N)(< K)的子集和的最大值

    (s_i = left{ egin{array}{**lr**} s_{i + 1} (if a_i + s_{i +1}geq K)\ a_i + s_{i + 1} (if a_i + s_{i + 1}< K) end{array} ight.)
    (s_i)可将只考虑(i ~ N)(i)不是"不必要"的条件改写成
    (s_{i + 1}geq K - a_i)也即 (a_i + s_{i + 1}geq K)
    下面分情况讨论:

    • 如果(a_i + s_{i + 1}geq K) 那么在只考虑(i ~ N)(i)不是不必要的 所以(p_i = 0)
    • 如果(a_i + s_{i + 1} < K) 那么 (p_i = p_{i + 1} + 1)
      最后答案为 (p_1)
      时间复杂度:(O(NlogN))

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll n,k,a[1000000],s,p;
    bool cmp(ll x,ll y)
    {
    	return x > y;
    }
    int main()
    {
    	freopen("unnecessary.in","r",stdin);
    	freopen("unnecessary.out","w",stdout);
    	scanf("%lld%lld",&n,&k);
    	for(ll i = 1;i <= n;i++)
    	scanf("%lld",&a[i]);
    	sort(a + 1,a + n + 1,cmp);
    	for(ll i = 1;i <= n;i++)
    	{
    		if(s + a[i] >= k)
    		p = 0;
    		else
    		p += 1,s = s + a[i];
    	}
    	cout<<p;
    }
    

    C

    大意:给定了一个数列 (A_1,A_2,······,A_n)
    一个区间的权值为:
    (W(L,R)=(R−L+1)×gcd(A_l,...,A_r))
    (W_max)

    考场上

    打了个暴力 加了个剪枝
    水到了70

    **#include<iostream>
    #include<cstdio>
    #define ll long long 
    using namespace std;
    ll gcd(ll a,ll b)
    {
    	return a == 0?b:gcd(b%a,a);
    }
    ll read()
    {
    	ll f = 1,ans = 0;
    	char a;
    	a = getchar();
    	while(a != '-' && (a >'9'||a <'0'))
    	a = getchar();
    	if(a == '-')f = -1,a = getchar();
    	while(a <= '9' && a >= '0')
    	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
    	return ans * f;
    }
    ll n,a[100005],ans;
    int main()
    {
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);   
        n = read();
        for(ll i = 1;i <= n;i++)
        a[i] = read();
        for(ll l = 1;l <= n;l++)
        {
        	ll g = a[l];
        	for(ll r = l;r <= n;r++)
            {
            	g = gcd(g,a[r]);
            	ans = max(ans,g * (r - l + 1));
            	if(g * (n - l + 1) <= ans)//利用gcd向右扩张只会减少不会增加
            	break;        	
    		}
    	}
    	cout<<ans;
    }
    

    正解:

    有分治的做法 但是这里用(O(nlog^2n))的方法
    我们对于一个r 我们知道左边的(gcd(a[l]...a[r])gcd(a[l]...a[r]))一定小于等于(gcd(a[l+1]...a[r])gcd(a[l+1]...a[r]))
    同时对于一个数m 如果他和别的数的(gcd)不等于m 则必定小于(m/2) 所以最多对于一个区间有(logn)(gcd)
    所以我们枚举r,用一个队列存储这log个不同的gcd的左端点,每次直接枚举这些gcd更新,更新的时候加一些判断处理重复就好了,写起来很容易。

    代码

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define ll long long
    using namespace std;
    ll n;
    queue<int> QAQ;
    queue<int> lins;
    ll g[100005],ans;
    ll gcd(ll x,ll y)
    {return (x == 0)? y : gcd(y % x,x);}
    int main()
    {
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);	
    	scanf("%lld",&n);
    	g[0] = -1;
    	for(ll i = 1;i <= n;i++)
    	{
    		scanf("%lld",&g[i]);//输入
    		int last = 0;//上一个gcd段的最后的一位
    		while(!QAQ.empty()) 
    		{
    		    ll  x = QAQ.front();	
    		    QAQ.pop();
    		    g[x] = gcd(g[x],g[i]);
    		    ans = max(ans,g[x] * (i - x + 1));//计算权值 
    		    if(g[x] == g[last])continue;//如果和上一段一样则不必存
    			lins.push(x);
    			last = x; 
    		}
    		ans = max(ans,g[i]);
    		while(!lins.empty())
    		{
    			QAQ.push(lins.front());
    			lins.pop();
    		} 
    		if(g[last] != g[i]) QAQ.push(i);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    D

    4.1 问题描述
    沙都子热衷于制造陷阱。她制造了一个 (n × n) 的陷阱,其中 (n) 为奇数 奇数。第 i 行
    第 j 列的区域的伤害值为 (a_{i,j}),如果 (a_{i,j} < 0) 则说明这一区域会帮其回血。
    但沙都子对这个陷阱不太满意,打算对其进行改造。沙都子太懒,不想一个格
    子一个格子改造。令 (m = (n + 1)/2),每一次沙都子会将一个 (m × m)的连续子
    矩形的伤害值都乘上 (−1)。沙都子想知道,经过若干次改造后,陷阱所有区域的
    伤害值之和最大是多少呢?
    4.2 任务描述
    4.2.1 输入
    第一行,一个正整数 n,保证 n 为奇数。
    接下来 n 行,每行 n 个整数 a i,j ,表示初始伤害值。
    4.2.2 输出
    一行,表示进行若干次改造后,陷阱所有区域的伤害值之和的最大值。

    考场上:

    被样例误导了 以为这个(m x m)的矩阵只会在四周
    然后码了很久
    最后5分。。。
    要注意看题

    正解(采用STD)

    代码

    #include <cstdio>
    #include <algorithm>
    #define N_MAX 35
    #define M_MAX ((N_MAX + 1) / 2)
    const int INF = 0x3F3F3F3F;
    inline int f(int t, int v) { return t ? -v : v; }
    int n, m, i, j, s, t, a[N_MAX + 1][N_MAX + 1], sum, tmp, cur, ans = -INF;
    
    #define FIO "trap"
    int main()
    {
    	freopen(FIO ".in", "r", stdin);
    	freopen(FIO ".out", "w", stdout);
    
    	scanf("%d", &n);
    	for (i = 1; i <= n; ++i)
    		for (j = 1; j <= n; ++j)
    			scanf("%d", &a[i][j]);
    	m = n + 1 >> 1;
    	for (t = 0; t < 1 << m; ++t)
    	{
    		cur = f(t & 1, a[m][m]);
    		for (j = 1; j < m; ++j)
    			cur += f(t >> j & 1, a[m][j]);
    		for (j = 1; j < m; ++j)
    			cur += f(t & 1 ^ t >> j & 1, a[m][j + m]);
    		for (i = 1; i < m; ++i)
    		{
    			tmp = -INF;
    			for (s = 0; s < 2; ++s)
    			{
    				sum = f(s, a[i][m]) + f(s ^ t & 1, a[i + m][m]);
    				for (j = 1; j < m; ++j)
    					sum += std::abs(a[i][j] + f(s, a[i][j + m]) + f(t >> j & 1, a[i + m][j]) + f(s ^ t & 1 ^ t >> j & 1, a[i + m][j + m]));
    				tmp = std::max(tmp, sum);
    			}
    			cur += tmp;
    		}
    		ans = std::max(ans, cur);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    第十六周 项目一-平方根中的异常
    LeetCode之小孩分糖果
    C#中怎样将List&lt;自己定义&gt;转为Json格式 及相关函数-DataContractJsonSerializer
    (016)给定一个有序数组(递增),敲代码构建一棵具有最小高度的二叉树(keep it up)
    物化视图
    FZU2171:防守阵地 II(线段树)
    鸡尾酒排序
    Android BlueDroid(三):BlueDroid蓝牙开启过程enable
    CF Codeforces Round #256 (Div. 2) D (448D) Multiplication Table
    window.open()具体解释及浏览器兼容性问题
  • 原文地址:https://www.cnblogs.com/dixiao/p/13759086.html
Copyright © 2011-2022 走看看