Codeforces Round 961 (Div. 2)(A-D)

A. Diagonals

根据题目定义对角线显然从左上到右下,那么显然一个n*n的矩形有2n-1个对角线,把所有对角线取出后排序为n,n-1,n-1,n-2,n-2...1,1,从大到小用m减去即可。

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define ll long long
#define endl "\n"
#define pb push_back
#define pii pair<int, int>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 2e5 + 20;
int n, m;
int a[N];
void solve()
{
    cin >> n >> m;
    int idx = 0;
    a[++idx] = n;
    pre(i, n - 1, 1)
    {
        a[++idx] = i;
        a[++idx] = i;
    }
    int cnt = 0;
    rep(i, 1, idx)
    {
        if(m <= 0) break;
        m -= a[i];
        cnt ++ ;
    }
    cout << cnt << endl;
}
int main()
{
	IOS;
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

B2. Bouquet (Hard Version)

这题赛时直接去写hard了,仅提供hard的做法。

由于组合的花花瓣差不超过1,因此用map统计一下花瓣数为x的花有多少个,然后遍历一遍,对于两个差为1的,我们优先用花瓣数小的,因为这样会发现当优先使用小的那个去填不够的用大的补,会发现在塞不下之后可以通过去掉一个小的,换上一个大的,从而使得答案加一,因此只需要先用小的然后算出能换多少大的即可。

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define int long long
#define endl "\n"
#define pb push_back
#define pii pair<int, int>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 2e5 + 20;
int n, m;
int a[N], b[N];
void solve()
{
    cin >> n >> m;
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, n) cin >> b[i];
    map<int, int>mp;
    rep(i, 1, n) mp[a[i]] += b[i] ;
    int last = 0, ans = 0;
    for(auto [x, y] : mp)
    {
        int cnt = m / x;
        cnt = min(cnt, y);
        ans = max(ans, cnt * x);
        if(!last) last = x;
        else if(x - last == 1)
        {
            int ct = m / last;
            ct = min(ct, mp[last]);
            int tt = m - ct * last;
            int ttt = y;
            if(tt >= x)
            {
                int ndd = tt / x;
                ndd = min(ndd, y);
                ttt -= ndd;
                tt -= ndd * x;
            }
            //if(last == 206)cout<<tt;
            int nd = min(tt, min(ct, ttt));
            tt -= nd;
            ans = max(ans, m - tt);
        }
        last = x;
    }
    cout << ans << endl;
}
signed main()
{
	IOS;
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

C. Squaring

可以发现直接贪心就是最后的答案,可是难点在于比较相邻两个数的大小,因为操作次数多会爆longlong。因为a的大小只有1e6,因为如果a_{i}<a_{i-1}那么a_{i}最多需要5次操作就可以比前一个数大,那么此时在使用和前一个数一样多的操作就可以保证大于前一个数,因此当前的数最多只比前一个数多操作5次。直接暴力枚举操作数即可。为了防止爆longlong当前使用的次数可以用前一个数减去来比较。

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define ll long long
#define endl "\n"
#define pb push_back
#define pii pair<int, int>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 1e6 + 20;
int n, m;
int a[N];
int sum[N];
double mp[N];
long long mpp[N];
double l2[N];
void solve()
{
    scanf("%d", &n);
    rep(i, 1, n) scanf("%d", &a[i]), sum[i] = 0;
    rep(i, 2, n)
    {
        if(a[i] < a[i - 1] && a[i] == 1)
        {
            printf("-1\n");
            return;
        }
    }
    rep(i, 2, n)
    {
        int x = max(0, sum[i - 1] - 20);
        while((double)pow(a[i - 1], (double)pow(2, (double)sum[i - 1] - x)) > 1.0 * a[i] && x < sum[i - 1] + 5)
        {
            x ++ ;
        }
        sum[i] = x;
        
    }
    long long ans = 0;
    rep(i, 1, n) ans += sum[i];
    printf("%lld\n", ans);
}
int main()
{
	int t;
	t = 1;
	scanf("%d", &t);
	while(t -- )
	{
		solve();
	}
	return 0;
}

D. Cases

范围明显是状压dp,考虑如何设计。

题目要求每k个连续的子串都至少有一个结尾字母,那么显然对于一段连续k个字母的子串,如果其中的每种字母在整个串都没有作为结尾出现那么一定是不合法的。如果最后一个字母不是结尾那一定也不合法。设一个状态s,s的二进制位为1表示这一位代表的字母没有作为结尾。那么刚才提到的两个不合法状态就可以初始化为0,其余状态初始化为1。最后集合从小到大枚举,看当前集合是否有不合法的子集即可。答案就是合法集合中二进制位0最少的个数。

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define ll long long
#define endl "\n"
#define pb push_back
#define pii pair<int, int>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 1e6 + 20;
int n, m, k;
int a[N], dp[1 << 18];
void solve()
{
    cin >> n >> m >> k;
    rep(i, 0, (1 << m) - 1) dp[i] = 1;
    string s;
    cin >> s;
    s = " " + s;
    int now = 0;
    map<char, int>mp;
    rep(i, 1, n)
    {
        mp[s[i]] ++ ;
        now |= (1 << (s[i] - 'A'));
        if(i - k > 0) 
        {
            mp[s[i - k]] -- ;
            if(mp[s[i - k]] == 0) now -= (1 << (s[i - k] - 'A'));
        }
        if(i >= k) dp[now] = 0;
    }
    rep(i, 0, (1 << m) - 1)
    {
        if(i >> (s[n] - 'A') & 1) dp[i] = 0;
    }
    rep(i, 0, (1 << m) - 1)
    {
        rep(j, 0, m - 1)
        {
            if(i >> j & 1) dp[i] &= dp[i - (1 << j)];
        }
    }
    int ans = 100;
    rep(i, 0, (1 << m) - 1)
    {
        if(dp[i])
        {
            int cnt = 0;
            rep(j, 0, m - 1)
            {
                if(!(i >> j & 1)) cnt ++ ;
            }
            ans = min(ans, cnt);
        }
    }
    cout << ans << endl;
}
int main()
{
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,根据提供的引用内容,我无法理解你具体想要问什么问题。请提供更清晰明确的问题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【CodeforcesCodeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值