最近也写了些许题目吧,还是写写博客,捋捋思路。

P2216 [HAOI2007]理想的正方形

求一个$a \times b(a,b \leq 10^3)$的矩阵,求出一个$n \times n (n \leq 100)$的矩阵,设矩阵中元素最小值$Min$,最大值$Max$,

最小化$Max - Min$

Sol : 这个题事实上只需要暴力扫每个子矩阵即可。复杂度是$O(abn)$

预处理对点$(i,j)$的$ Max[i][j] = \max\limits_{k=i-n+1}^{i} a[k][j]$

枚举每个子矩阵的时候,求$(i,j)$为左下角的$n \times n$子矩阵的

$MAX=\max\limits_{k=j-n+1}^{j} Max[i][k]$而$MIN$的处理同理。

// luogu-judger-enable-o2
# include<bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e3+;
int w[N][N];
int Max[N][N],Min[N][N];
int a,b,n,ans=0x3f3f3f3f;
signed main()
{
scanf("%lld%lld%lld",&a,&b,&n);
for (int i=;i<=a;i++)
for (int j=;j<=b;j++)
scanf("%lld",&w[i][j]);
memset(Max,-0x3f,sizeof(Max));
memset(Min,0x3f,sizeof(Min));
for (int i=;i<=a;i++)
for (int j=;j<=b;j++) {
if (j<n) continue;
for (int k=j;k>=j-n+;k--)
Min[i][j]=min(Min[i][j],w[i][k]),
Max[i][j]=max(Max[i][j],w[i][k]);
}
for (int i=;i<=a;i++)
for (int j=;j<=b;j++) {
int mi=0x3f3f3f3f,ma=-0x3f3f3f3f;
if (i<n) continue;
for (int k=i;k>=i-n+;k--)
mi=min(mi,Min[k][j]),ma=max(ma,Max[k][j]);
if (ma-mi<ans&&ma-mi>=) ans=ma-mi;
}
printf("%lld\n",ans);
return ;
}

P2216.cpp

P2831 [NOIP2016D2T3] 愤怒的小鸟

有$n(n \leq 18 )$个小猪在平面直角坐标系中,小鸟可以从$(0,0)$出发以一条任意的$y = ax^2 + bx + c(a<0)$的抛物线消去飞行路线上的猪。

如要消除所有的猪,最小化所需鸟的个数。

Sol : 数据范围是搜索的复杂度,加最优性剪枝能过。

dfs(a,b,c)表示当前选择第$a$只猪,前确定了$b$条解析式,前面$c$只猪是单着被打中的(还没有确定一条解析式)

那么对于这只猪有三种决策:

A. 单独使用一只鸟击中。 B. 被之前确定的一条解析式打中。 C. 和之前某一只猪构成抛物线(三点构成一条抛物线)

然后就搜索就可以了, 加上最优性剪枝b+c > ans 直接return;

vector可以快速插入和删除好评!!!!

样例没过却AC的代码好评:https://www.luogu.org/recordnew/show/19042160

# include <bits/stdc++.h>
using namespace std;
const int N=;
const double eps=1e-;
struct rec{
double x,y;
}w[N];
int n,ans;
vector<int>single;
vector<pair<double,double> >pwx;
void dfs(int a,int b,int c)
{
if (b+c>=ans) return;
if (a>n) { ans=min(ans,b+c); return;}
single.push_back(a); dfs(a+,b,c+); single.pop_back();
bool ff=false;
for (int i=;i<pwx.size();++i) {
double pa=pwx[i].first,pb=pwx[i].second;
if (fabs(pa*w[a].x*w[a].x+pb*w[a].x-w[a].y)<=eps) {
dfs(a+,b,c);
ff=true; break;
}
}
if (ff) return;
for (int i=;i<single.size();++i) {
int id=single[i];
if (fabs(w[a].x-w[id].x)<=eps) continue;
double pa=(w[a].y*w[id].x-w[id].y*w[a].x)/(w[a].x*w[id].x*(w[a].x-w[id].x));
double pb=(w[a].y-pa*w[a].x*w[a].x)/w[a].x;
if (pa>=0.0) continue;
single.erase(single.begin()+i);
pwx.push_back(make_pair(pa,pb));
dfs(a+,b+,c-);
single.insert(single.begin()+i,id);
pwx.pop_back();
}
}
int main()
{
int T; scanf("%d",&T);
while (T--) {
ans=0x3f3f3f3f; single.clear(); pwx.clear();
int t; scanf("%d%d",&n,&t);
for (int i=;i<=n;i++) scanf("%lf%lf",&w[i].x,&w[i].y);
dfs(,,);
printf("%d\n",ans);
}
return ;
}

P2831.cpp

P5253 丢番图

求方程$\frac{1}{x} +\frac{1}{y} = \frac{1}{n} \ \ \ x,y,n \in N^*$  的解$(x,y) $其中$(x\leq y)$的组数。

对于100%的数据$n \leq 10^{14}$

Sol : 通分,得出 $nx + ny - xy = 0$ 构造得$(n-x)(n-y) = n^2$

等价于求$d(n^2)$ 然后发现$n^2$的比较大无法质因数分解,考虑对$n$分解质因数。

$ n = \sum\limits_{i=1}^{k} {a_i} ^ {p_i}$ 则 $n^2 = (\sum\limits_{i=1}^{k} {a_i} ^ {p_i})^2 = \sum\limits_{i=1}^{k} {a_i} ^ {2p_i}$

所以$d(n^2) = \prod\limits_{i=1}^{k} (2p_i + 1)$

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e7+;
int pr[N];
bool is_pr[N];
void EouLaSha(int Lim)
{
memset(is_pr,true,sizeof(is_pr));
is_pr[]=false;
for (int i=;i<=Lim;i++) {
if (is_pr[i]) pr[++pr[]]=i;
for (int j=;j<=pr[]&&i*pr[j]<=Lim;j++) {
is_pr[i*pr[j]]=false;
if (i%pr[j]==) break;
}
}
}
signed main()
{
EouLaSha(1e7);
int n; scanf("%lld",&n);
int ret=;
for (int i=;i<=pr[];i++)
if (n%pr[i]==) {
int times=;
while (n>&&n%pr[i]==) times++,n/=pr[i];
ret=ret*(*times+);
}
if (n>) ret=ret*(+);
printf("%lld\n",(ret+)>>);
return ;
}

P5253.cpp

P1084 [NOIP2012D2T3] 疫情控制

一棵$n(n \leq 5\times 10^4)$个节点的树上有$m (m \leq 5 \times 10^4)$个障碍,每个障碍可以移动,移动的代价就是树上最短路长度。

最小化移动这些障碍的最大代价使得从根节点$1$走到树的叶子节点的路径所构成集合为$\varnothing $

Sol :最小最大\最大最小 显然考虑二分答案。

对于一个合法的最大移动步数$Mid$,考虑怎么移动可以控制的叶子结点更多?

这个节点的目的地深度尽可能小。但是需要考虑过根节点$1$的可能。

标记节点可以到达$1$时,可能走到达和$1$相连的直接儿子,控制这棵子树。我们称之为帮助别人。

如果这个节点无法到达$1$,那么显然只需要让他到达他所能跳上来的深度最小的节点就行了,这样就可以控制最广阔的叶子。

如果我们经过这些处理以后,我们发现和$1$相连的某些节点所在子树的叶子无法被完全覆盖,那么我们称这个节点是需要帮助的。

显然一个需要帮助的节点需要一个帮助别人的节点的帮助。

若帮助别人的节点自己的子树还未完全覆盖,而且这个帮助别人的路径不足以重新到达自己所在的节点(相当于这个节点和1之间的路径走了2次),那么我们把这个节点取覆盖其所在子树的那个区间。

这是因为,如果不这样做,势必需要另外一个比当前帮助的长度要更长的帮助别人的节点来帮助,而不帮助自己的那个节点帮助别人的能力却比帮助这个节点的另外一个帮助者要差。这样比上述的方案更劣。

然后对剩余的需要帮助的节点和可以提供帮助的距离进行排序双指针判断是否可以覆盖即可。

树上向上跳可以用倍增优化。

复杂度是$O(m log_2 {n} log_2{w})$

// luogu-judger-enable-o2
# include<bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+;
bool mark[N];
int d[N][],b[N],g[N][],help[N],tmp[N];
int size[N],n,m;
vector<int>rec[N];
struct rec{
int pre,to,w;
}a[N<<];
int head[N],tot;
void dfs1(int u,int fa)
{
size[u]=; g[u][]=fa;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (v==fa) continue;
d[v][]=a[i].w;
dfs1(v,u);
size[u]+=size[v];
}
}
void init()
{
dfs1(,);
for (int i=;i<=;i++)
for (int j=;j<=n;j++)
g[j][i]=g[g[j][i-]][i-],
d[j][i]=d[j][i-]+d[g[j][i-]][i-];
}
void adde(int u,int v,int w)
{
a[++tot].pre=head[u];
a[tot].to=v;
a[tot].w=w;
head[u]=tot;
}
bool dfs2(int u,int fa)
{
if (mark[u]) return true;
if (size[u]==) {
if (mark[u]) return true;
else return false;
}
bool flag=true;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to;
if (v==fa||mark[v]) continue;
flag&=dfs2(v,u);
}
return flag;
}
bool check(int Mid)
{
memset(mark,false,sizeof(mark));
for (int i=;i<=n;i++) rec[i].clear();
for (int i=;i<=m;i++) {
int dist=,u=b[i];
for (int j=;j>=;j--)
if (g[u][j]>&&dist+d[u][j]<=Mid) {
dist+=d[u][j]; u=g[u][j];
}
if (g[u][]==) {
dist+=d[u][];
if (dist>Mid) mark[u]=true;
else {
rec[u].push_back(Mid-dist);
}
} else mark[u]=true;
}
for (int i=;i<=n;i++) sort(rec[i].begin(),rec[i].end());
help[]=;
for (int i=head[];i;i=a[i].pre) {
int v=a[i].to; if (dfs2(v,)) continue;
bool flag=true;
for (int j=;j<rec[v].size();j++)
if (rec[v][j]<a[i].w) { rec[v].erase(rec[v].begin()+j);flag=false;break;}
if (!flag) continue;
help[++help[]]=a[i].w;
}
tmp[]=;
for (int i=head[];i;i=a[i].pre) {
int v=a[i].to;
for (int j=;j<rec[v].size();j++)
tmp[++tmp[]]=rec[v][j];
}
sort(tmp+,tmp++tmp[]);
sort(help+,help++help[]);
if (help[]==) return true;
int pt1=,pt2=;
while (pt1<=tmp[]) {
if (pt2>help[]) return true;
while (tmp[pt1]>=help[pt2]&&pt2<=help[]&&pt1<=tmp[]) pt1++,pt2++;
if (pt2>help[]) return true;
pt1++;
}
return false;
}
signed main()
{
scanf("%lld",&n);
int l=,r=,ans=-;
for (int i=;i<n;i++) {
int u,v,w; scanf("%lld%lld%lld",&u,&v,&w); r+=w;
adde(u,v,w); adde(v,u,w);
}
scanf("%lld",&m);
for (int i=;i<=m;i++) scanf("%lld",&b[i]);
init();
while (l<=r) {
int mid=(l+r)>>;
if (check(mid)) ans=mid,r=mid-;
else l=mid+;
}
printf("%lld\n",ans);
return ;
}

P1084.cpp

一些简单题(1)(Source : NOIP历年试题+杂题)的更多相关文章

  1. 一些简单题(2)(Source : NOIP历年试题+杂题)

    P3084 [USACO13OPEN]照片Photo 给出$m$个区间$[l_i,r_i]$覆盖$S=[1,n]$,试确定最大特殊点的数使得这每一个区间覆盖且仅覆盖一个特殊点. 如果无解,输出$-1$ ...

  2. NOIP 历年试题大致考点总结

    总的来说,水平还不够-- 要努力了! NOIP2012 D1T1 模拟, 字符串 D1T2 贪心, 数学 (推导贪心策略), 高精度 D1T3 unsolved 开车旅行 倍增 D2T1 解线性模方程 ...

  3. noip历年试题

      noip2018 铺设道路 货币系统 赛道修建 一眼贪心.随便实现. 旅行 环套树枚举删除环上哪条边. 填数游戏 找规律,这谁会啊. 保卫王国 动态Dp,去问这位神仙.   noip2017 小凯 ...

  4. 2016 10 26考试 NOIP模拟赛 杂题

    Time 7:50 AM -> 11:15 AM 感觉今天考完后,我的内心是崩溃的 试题 考试包 T1: 首先看起来是个贪心,然而,然而,看到那个100%数据为n <= 2000整个人就虚 ...

  5. 贪心/构造/DP 杂题选做Ⅲ

    颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...

  6. 剑指Offer——网易校招内推笔试题+模拟题知识点总结

    剑指Offer--网易校招内推笔试题+模拟题知识点总结 前言 2016.8.2 19:00网易校招内推笔试开始进行.前天晚上利用大约1小时时间完成了测评(这个必须做,关切到你能否参与面试).上午利用2 ...

  7. NOIP前的刷题记录

    因为这几天要加油,懒得每篇都来写题解了,就这里记录一下加上一句话题解好了 P4071 [SDOI2016]排列计数   组合数+错排 loj 6217 扑克牌 暴力背包 P2511 [HAOI2008 ...

  8. CCF认证历年试题

    CCF认证历年试题 不加索引整理会死星人orz 第一题: CCF201712-1 最小差值(100分) CCF201709-1 打酱油(100分) CCF201703-1 分蛋糕(100分) CCF2 ...

  9. 11.14 noip模拟试题

      题目名称 正确答案 序列问题 长途旅行 英文名称 answer sequence travel 输入文件名 answer.in sequence.in travel.in 输出文件名 answer ...

随机推荐

  1. 初次shell编程

    虽然说的是初次shell写xhell脚本,但是其实我也写了三.四个简单的脚本了.现在总结下写简单的shell脚本中遇到的一些小问题备忘一下吧. 首先是脚本文件是已.sh作为后缀的,可以先建一个.sh的 ...

  2. 什么是数据传输服务DTS

    数据传输服务(Data Transmission Service) DTS支持关系型数据库.NoSQL.大数据(OLAP)等数据源间的数据传输. 它是一种集数据迁移.数据订阅及数据实时同步于一体的数据 ...

  3. Entity Framework常用方法及案例

    ⒈Skip(int count) 说明:跳过集合的前n个元素:延迟.即我们跳过给定的数目返回后面的结果集. ⒉Take(int count) 说明:获取集合的前n个元素:延迟.即只返回限定数量的结果集 ...

  4. vue : 无法加载文件 C:\Users\lihongjie\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 htt ps:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 + vue init webpack vue_p

    以管理员方式打开powershell 运行命令:set-ExecutionPolicy RemoteSigned 出现: 执行策略更改执行策略可帮助你防止执行不信任的脚本.更改执行策略可能会产生安全风 ...

  5. mac 下安装mysql8.0

    有两种安装方式,一种是安装包安装,官网下载安装包,mysql8.0下载.mysql5.7安装: 这里记录brew安装: 1.brew uninstall mysql 卸载原有的: 2.brew ins ...

  6. qt treaview项checkbox样式

    QTreeView::indicator:enabled:checked { /** 指示器 - 选中 **/ image: url(yzfx/checkbox_checked.png);}QTree ...

  7. cookie和session的详解和区别

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  8. Gcc 安装过程中部分配置

    Gcc 安装过程中部分配置详解 全文参考<have fun with Gcc>一文,如有需要请联系原作者prolj@163.com 解压gcc源码后,需要进行configure,这时候一般 ...

  9. SpringBoot之使用Druid连接池以及SQL监控和spring监控

    一.引入maven依赖 <dependencies> <dependency> <groupId>org.springframework.boot</grou ...

  10. Hyperledger Fabric(4)链码ChainCode

    智能合约,是一个抽象的概念,智能合约的历史可以追溯到 1990s 年代.它是由尼克萨博(Nick Szabo)提出的理念,几乎与互联网同龄. 我们这里所说的智能合约只狭义的指区块链中.它能够部署和运行 ...