首页 > 其他分享 >B0704 模拟赛题解

B0704 模拟赛题解

时间:2023-07-05 11:25:58浏览次数:52  
标签:11 lc la int 题解 mid ra B0704 模拟

原题链接

前言

挂分最多的一场。
考虑到之前都无分可挂,这场算是最近很简单的了。

T1 不排序(按理说我的做法不需要排,但挂了),100->40。

T2 二分某个边界时单调性判错,100->30。

T3 原,但没做过。

T4 某人用模拟退火骗到 60 pts orz。

T1 棍子

签到题。

考虑二分答案。显然每次要切的长度应等于二分的这个答案。

代码就不贴了。

T2 数组

签到题 \(\times 2\)。

显然 \(ans=\sum\limits_{i=la}^{ra} \min(rc/i,rb)-\max(\lceil lc/i \rceil,lb)+1\)。

分别整除分块统计即可。

对于向上取整的整除分块,从后往前,每次求左边界。

注意区间可能为负,讨论下单调性,二分下边界即可。

#include<bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
using namespace std;

int la,ra,lb,rb,lc,rc,s1,s2;
inline int d(int a,int b) {return ceil(1.0*a/b);}

main()
{
	cin>>la>>ra>>lb>>rb>>lc>>rc;
	int t=-1,l=la,r=ra;
	while(l<=r)
	{
		if(rc/mid>=d(lc,mid)&&rc/mid>=lb) t=mid,l=mid+1;
		else r=mid-1;
	}
	ra=min(ra,t);
	t=-1,l=la,r=ra;
	while(l<=r)
	{
		if(rb>=d(lc,mid)) t=mid,r=mid-1;
		else l=mid+1;
	}
	if(~t) la=max(la,t);
	for(int l=la,r;l<=ra&&rc/l!=0;l=r+1) r=min(rc/(rc/l),ra),s1+=(r-l+1)*min(rc/l,rb);
	for(int r=ra,l;r>=la&&d(lc,r)!=0;r=l-1) l=max(d(lc,(d(lc,r))),la),s2+=(r-l+1)*max(d(lc,r),lb);
	cout<<s1-s2+ra-la+1<<'\n';
}

T3 十一

不仅是之前模拟赛原题(我没打),还是 CF856C

其实挺难想的,但不抽象,感觉比 T4 难想。

\(11\) 倍数的特点。

注意到 \(10 \equiv -1 \pmod {11}\)。

考虑一个数 \(\overline{a_1a_2a_3a_4}\) 对 \(11\) 取模。

可以发现 \(-1\) 幂的正负性只与幂次的奇偶性有关,即当前数位的奇偶性相关。

\(10^4a_1+10^3a_2+10^2a_3+10a_4 \equiv a_1-a_2+a_3-a_4 \pmod {11}\)。

定义一个数 \(\overline{a_1a_2...a_n}\) 的值为 \(\sum\limits_{i=1}^{n} (-1)^{i-1}a_{i}\)。

那么每个数的值的贡献可能是正,也可能是负。

为方便,下面奇数指数位为奇数的数,偶数定义类似。

注意到在任何位置插入偶数不会影响之前的贡献。

于是考虑奇偶分别讨论。

对于奇数:

值从前往后显然是 \(...-+-+-+\),且是固定的。这很显然可以 dp。

设 \(f(i,j,k)\) 表示填到第 \(i\) 个奇数,填了 \(j\) 个正位,对 \(11\) 取模后值为 \(k\) 的方案。

讨论一下第 \(i\) 个数填正位还是负位,记正位共有 \(odd\) 个,负位共有 \(even\) 个,不难得出状态转移方程:

\(f(i,j,k)=f(i-1,j-1,k-a_i)\cdot(odd-j+1)+f(i-1,j,k+a_i)\cdot(even-i+1-j)\)。

对于偶数:

考虑在奇数固定位置上插入偶数。

注意每插入一个数,就会多出一个可以插的位置。

设 \(g(i,j,k)\) 表示填到第 \(i\) 个偶数,\(j,k\) 意义同上。转移与上类似,注意下枚举范围即可。

最后累计下答案即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=52,mod=1e9+7;
int n,lp,lq,p[N],q[N],f[N][N][11],g[N][N][11];
inline int mt(int x) {return (x%11+11)%11;}

main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		string s;cin>>s;
		int a=0,t=1;
		for(int i:s) a+=t*(i-'0'),t=-t;
		if(s.size()&1) p[++lp]=a;
		else q[++lq]=a;
	}
	f[0][0][0]=1;
	int odd=ceil(lp/2.0);
	for(int i=1;i<=lp;i++)
		for(int j=0;j<=odd;j++)
			for(int k=0;k<11;k++)
				f[i][j][k]=((j?f[i-1][j-1][mt(k-p[i])]*(odd-j+1):0)+f[i-1][j][mt(k+p[i])]*max(0ll,(lp-odd-i+1+j)))%mod;
	g[0][0][0]=1;
	for(int i=1;i<=lq;i++)
		for(int j=0;j<=i;j++)
			for(int k=0;k<11;k++)
				g[i][j][k]=((j?g[i-1][j-1][mt(k-q[i])]*(odd+j-1):0)+g[i-1][j][mt(k+q[i])]*(lp-odd+i-j))%mod;
	int ans=0;
	for(int j=0;j<=lq;j++)
		for(int k=0;k<11;k++)
			ans=(ans+f[lp][odd][k]*g[lq][j][mt(-k)]%mod)%mod;
	cout<<ans;
}

T4 棋盘

经典的,于我而言初见的,将曼哈顿距离转化为切比雪夫距离。

切比雪夫距离:对于两个点 \((x_1,y_1),(x_2,y_2)\),切比雪夫距离为 \(max(|x1-x2|,|y1-y2|)\)。

转化方法:用两种距离距原点分别为 \(1\) 的点作图,观察,旋转即可。

可以发现让 \((x,y)\) 映射为 \((x+y,x-y)\) 即可。

假设映射完后图长这样:

...#....
........
.......#
........
.#.#....
....#...
........
...#....

每次删点,距其最远的点一定在四个边界上。

直觉+脑糊,会发现每次删边界上的点一定是不劣的。这里就不证明了,其实很显然。

且每次会选边界跨度更大的那两个点其中之一删去。

可以考虑记搜,状态为点集。复杂度玄学,跑得很快就是了。

#include<bits/stdc++.h>
using namespace std;

int n;
char c[9][9];
struct node{
    int x,y;
    bool operator<(const node &a)const{
        return x==a.x?y<a.y:x<a.x;
    }
};
vector<node> p;
map<vector<node>,int> f;

int dfs(vector<node> s)
{
    if(s.size()<=1) return f[s]=0;
    if(f.count(s)) return f[s];
    int x1=0,x2=0,y1=0,y2=0;
    for(int i=0;i<s.size();i++)
    {
        auto [x,y]=s[i];
        if(x<s[x1].x) x1=i;
        if(x>s[x2].x) x2=i;
        if(y<s[y1].y) y1=i;
        if(y>s[y2].y) y2=i;
    }
    if(s[x2].x-s[x1].x<s[y2].y-s[y1].y) swap(x1,y1),swap(x2,y2);
    int v1=0,v2=0;
    vector<node> s1,s2;
    for(int i=0;i<s.size();i++)
    {
        if(i!=x1) v1=max(v1,max(abs(s[x1].x-s[i].x),abs(s[x1].y-s[i].y))),s1.push_back(s[i]);
        if(i!=x2) v2=max(v2,max(abs(s[x2].x-s[i].x),abs(s[x2].y-s[i].y))),s2.push_back(s[i]);
    }
    int f1=dfs(s1)+v1,f2=dfs(s2)+v2;
    return f[s]=min(f1,f2);
}

int main()
{
    for(int i=1;i<=8;i++)
        for(int j=1;j<=8;j++)
        {
            cin>>c[i][j];
            if(c[i][j]=='#') p.push_back({i+j,i-j});
        }
    cout<<dfs(p);
}

标签:11,lc,la,int,题解,mid,ra,B0704,模拟
From: https://www.cnblogs.com/spider-oyster/p/17528014.html

相关文章

  • SPOJ Substrings 题解
    \(\text{SAM}\)入门好题。首先我们需要知道几个关于\(\text{SAM}\)的结论。结论1:题目中的\(f(x)\)单调下降。显然,对于长度为\(x\)的子串,其必存在一个\(x-1\)的后缀,这个后缀的\(\text{endpos}\)集合肯定包含子串的\(\text{endpos}\)集合,所以必有\(f(x-1)\le......
  • Hydro #4766. 文艺计算姬 题解--zhengjun
    link前置知识:Prufer序列,二分图别的题解都是直接给答案,没有比较易懂的思路。首先,考虑Prufer序列,发现右边点删除一定会加入一个左边点,另一边类似。且生成Prufer序列的最后一定会留下左右边各一个点。所以左边点在Prufer序列中出现的次数即为\(m-1\),右边即为\(n-1\)。......
  • 模拟双色球彩票系统(java)
    一、问题描述 注:六个红色球号码均不同,蓝色球号码可以红色球号码相同;二、设计思路(1)先随机出一个中奖号码,依据这个号码对后续进行颁奖;(2)再从用户端接收对应的6个红色球号码以及1个蓝色球号码;(3)将中奖号码与用户号码进行对比,得出对应的中奖结果;ps:”如何得到不重复的随机数“值......
  • Siege-压力模拟/测试工具
     Siege(英文意思是围攻)是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。 最早使用的压力测试工具是apache的ab(apachebenchmark),apach......
  • 【Maven】Unknown lifecycle phase “.test.skip=true“.问题解决
    我们在运行跳过单元测试时的命令mvnpackage-Dmaven.test.skip=true时,出现Unknownlifecyclephase".test.skip=true".如下[ERROR]Unknownlifecyclephase".test.skip=true".Youmustspecifyavalidlifecyclephaseoragoalintheformat<plugin-prefix>......
  • [总结]2023-7-4A组模拟赛
    [总结]2023-7-4A组模拟赛P1心路历程开题看到T1大概是个结论、T2似乎是倒序而且暴力可以拿很多分、T3不会、T4没想法。先想T1,以为是一个结论题。想了很久,没有结果,然后就在怀疑自己是否能做出来这种结论题。之后就弃疗了。看到T2,40%的很好拿,50%不妨考虑离线之后倒序,用并查集维......
  • PAT乙级【Java题解合集】
    ✨说在前面       这个暑假博主用大概两周不到的闲暇时间把PAT乙级的110道算法题全部肝完了,个人感觉题目的难度大部分在中等偏下,大概有二十道左右的题目还是蛮有意思的,值得细细去钻研,本专栏非常适合新手入门算法,也适合Java算法老手巩固一些基本知识点,由于C站上关于PAT乙级J......
  • 牛客练习赛 112 B~C题题解
    卡B题了,难受B.qsggandSubarrayB-qsggandSubarray_牛客练习赛112(nowcoder.com)题意给定一个长为n的序列,求有多少个子区间的按位与和为0。思路要想按位与之和为0,那么对于区间的所有数,每个二进制位都要有一个0。设f[i]表示二进制位i的最右边一个0出现的位置,枚举序列的每......
  • ABC306E 题解
    题目链接题目大意维护一个数据结构,数列长度为\(n\),\(q\)次操作,每次操作修改一个位置上的值,每次操作后输出数列里前\(k\)小的数的和(\(k\)是给定的)。\(n,k,q\leq5\times10^5\)值域\(1\times10^9\)题目分析开一棵权值线段树,每个节点储存对应区间的数的个数和数的和,......
  • ABC306F 题解
    题目链接题目大意对于\(S_1\capS_2=\emptyset\),定义长度为\(|S_1|+|S_2|\)的序列\(A\),为\(S_1\cupS_2\)排序后的结果。定义二元函数\(f(S_1,S_2)=\sum\limits_{1\leqi\leq|S_1|+|S_2|}i\times[A_i\inS_1]\)。给定\(n\)个大小为\(m\)的正整数集合\(S\)......