T1:入阵曲

  题目大意:给定一个N*M的矩形,问一共有多少个子矩形,使得矩形内所有书的和为k的倍数。

  60%:N,M<=80

    枚举矩形的左上角和右下角,用二维前缀和求出数字之和。

    时间复杂度$O(N^4)$

  100%

    我们发现美剧每个矩形的复杂度已经为N4,那么我们改为枚举矩形的边界。先枚举左右边界,再从上到下枚举下边界,两个矩形相减便可得出所有矩形,枚举时将每个矩形的区间和压入桶中,每次枚举时直接在桶中查询,左右边界更换时清桶。注意下边界要从0开始枚举。

    时间复杂度$O(N^3)$

    记得要卡常。

Code:

 #include<iostream>
#include<cstdio>
const int L=<<|;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
#define LL unsigned long long
#define rint register unsigned int
using namespace std;
const unsigned int N=;
int n,m,d;
int s[N][N];
unsigned int dfn[],t[];
inline int read()
{
rint s=;char c=getchar();
while(c<||c>) c=getchar();
while(c>=&&c<=)s=(s<<)+(s<<)+(c^),c=getchar();
return s;
}
int main()
{
n=read();m=read();d=read();
for(rint i=;i<=n;++i){
for(rint j=;j<=m;++j)
s[i][j]=(s[i-][j]+s[i][j-]-s[i-][j-]+read())%d;
}
LL ans=;rint df=;
for(rint i=;i<=m;++i){
for(rint j=i;j<=m;++j){
dfn[]=++df;t[]=;
for(rint k=;k<=n;++k){
register int now=((s[k][j]-s[k][j-i])%d+d)%d;
if(dfn[now]!=df){
dfn[now]=df;t[now]=;
}
else{
ans+=t[now];++t[now];
}
}
}
}
printf("%lld\n",ans);
return ;
}

T1

T2:将军令:

  题目大意:给定一棵树,和一个距离K,在某个节点驻扎军队可以占领所有与该节点距离不超过K的点,求最少要驻扎多少军队。

  此题和小胖守皇宫类似,不过权值均为一,可以用贪心做。

  将所有的点按深度排序,从前往后扫,遇到未标记的点,则从他的K辈祖先处开始进行dfs,暴力标记,将ans加一,扫到最后的结果即是答案。

  贪心策略证明:

    由于每次找的是深度最大的点,那么每次dfs一定能标记到当前子树的所有儿子,同时要想使其他子树需要的军队尽可能少,则应再次条件下尽可能向上,越向上越能标记更多的点。证明完毕,贪心策略正确。

  时间复杂度$O(NK)$

Code:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=;
int n,k,t,m=,ans=;
int fi[N],d[N],f[N];
bool v[N];
struct edge{
int v,ne;
}e[N<<];
struct point{
int d,id;
}p[N];
void add(int x,int y)
{
e[++m].v=y;
e[m].ne=fi[x];fi[x]=m;
}
bool comp(const point a1,const point a2)
{
return a1.d>a2.d;
}
int read()
{
int s=;char c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<=''){
s=(s<<)+(s<<)+c-'';
c=getchar();
}
return s;
}
void dfs(int x,int pa)
{
p[x].id=x;
for(int i=fi[x];i!=;i=e[i].ne){
int y=e[i].v;
if(y==pa) continue;
f[y]=x;
p[y].d=p[x].d+;
dfs(y,x);
}
}
void work(int x,int pa,int d)
{
v[x]=true;
if(d==) return;
for(int i=fi[x];i!=;i=e[i].ne){
int y=e[i].v;
if(y==pa) continue;
work(y,x,d-);
}
}
int main()
{
n=read();k=read();t=read();
for(int i=;i<n;i++){
int x=read(),y=read();
add(x,y);add(y,x);
}
p[].d=;dfs(,);
sort(p+,p+n+,comp);
for(int i=;i<=n;i++){
int x=p[i].id;
if(!v[x]){
for(int i=;i<=k&&f[x]!=;i++)
x=f[x];
work(x,,k);ans++;
}
}
printf("%d\n",ans);
return ;
}

T2

T3:星空

  题目大意:给一个0/1串,每次能将一个给定长度的区间去反,求最少要几次将整个串变为零。

  0/1串长度:N<=40000,区间长度数:M<=64,1的个数:K<=8

  24%做法:N<=16

    直接状压,跑BFS即可。DFS会T飞

  复杂度$O(N*2^N)$

  100%做法:

    我们发现相对于N,K很小,可以用来做做文章。

  开始转化题意:

    我们设灯亮为0,灯灭为1,则序列全为0时,所有灯都点亮。

    不难发现当N很大时,该序列中仅有K个1,我们从0位开始将每一位与其后一位亦或,则最多有2K个数与前一位不同,最多有2K个1,每次选择一段区间[L,R]取反,仅会改变第L-1位和第R位的值,相当于将序列中一定距离的点同时取反。

  题意转化为:给一个0/1串,每次选择相距给定长度的点同时取反,最少几次能将整个串全变为0。

  若选择的两个书均为0,没有任何意义;

  若选择的两个数均为1,则相互抵消;

  若其中一个数为0,另一个数为1,相当与将1移动一定距离。

  题意再次转化为:数轴上有最多2K个点,每次将一个点移动一段距离,两个点碰在一起后同时消失,最少几次能让所有点消失。

  此时K的范围状压可以接受,BFS算出两点间移动的最少次数,用状压DP简单解决。

  时间复杂度$O(MNK+K*2^K)$或$O(MNK+K^2*2^K)$

Code:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=;
const int inf=;
int n,k,m,tot=;
int a[N],b[N],v[N],c[],d[][],e[];
int dp[<<];
queue<int> q;
int read()
{
int s=;char c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<=''){
s=(s<<)+(s<<)+c-'';
c=getchar();
}
return s;
}
void bfs(int pos)
{
int now=c[pos];
memset(v,,sizeof(v));
v[now]=;q.push(now);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=;i<=m;i++){
int y=x+e[i];
if(y<=n+&&v[y]==){
v[y]=v[x]+;q.push(y);
}
y=x-e[i];
if(y>=&&v[y]==){
v[y]=v[x]+;q.push(y);
}
}
}
for(int i=;i<=tot;i++){
if(i!=pos){
if(v[c[i]]==) d[pos][i]=inf;
else d[pos][i]=v[c[i]]-;
}
}
}
int main()
{
n=read();k=read();m=read();
for(int i=;i<=k;i++){
int x=read();
a[x]=;
}
for(int i=;i<=n;i++){
b[i]=a[i]^a[i+];
if(b[i]==) c[++tot]=i+;
}
for(int i=;i<=m;i++)
e[i]=read();
for(int i=;i<=tot;i++)
bfs(i);
for(int i=;i<(<<tot);i++)
dp[i]=inf;
for(int i=;i<(<<tot);i++){
for(int j=;j<=tot;j++){
if(((i>>(j-))&)==) continue;
for(int g=;g<=tot;g++){
if(g==j) continue;
if(((i>>(g-))&)==) continue;
dp[i|(<<(j-))|(<<(g-))]=min(dp[i|(<<(j-))|(<<(g-))],dp[i]+d[j][g]);
}
}
}
printf("%d\n",dp[(<<tot)-]);
return ;
}

T3

NOIP模拟测试17的更多相关文章

  1. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

  2. 8.11 NOIP模拟测试17 入阵曲+将军令+星空

    T1 入阵曲 前缀和维护可以得60分 f[x1][y1][x2][y2]=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];  O(n4) ...

  3. NOIP模拟测试17「入阵曲&#183;将军令&#183;星空」

    入阵曲 题解 应用了一种美妙移项思想, 我们先考虑在一维上的做法 维护前缀和$(sum[r]-sum[l-1])\%k==0$可以转化为 $sum[r]\% k==sum[l-1]\%k$开个桶维护一 ...

  4. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  5. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  6. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  7. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  8. NOIP模拟测试1(2017081501)

    好,今天是cgg第一次举行模拟测试,希望各位支持. 时间限制:2小时 题目链接: 题目一:水得都没名字了 题目二:车站 题目三:选数 不要觉得2小时太少,我的题目很良心,都很简单. 答案可以在模拟测试 ...

  9. 「题解」NOIP模拟测试题解乱写I(29-31)

    NOIP模拟29(B) T1爬山 简单题,赛时找到了$O(1)$查询的规律于是切了. 从倍增LCA那里借鉴了一点东西:先将a.b抬到同一高度,然后再一起往上爬.所用的步数$×2$就是了. 抬升到同一高 ...

随机推荐

  1. 【leetcode】924.Minimize Malware Spread

    题目如下: In a network of nodes, each node i is directly connected to another node j if and only if grap ...

  2. cocos2D-X not config ndk path

    { 双击击那个error,那个路径就加上了 File = >local.properties }

  3. make编写教程(二)

    1. make中的变量 makefile中的变量就是c/c++中的宏 2. 引用其他的make文件 类似于c语言中的#include,被包含的文件会原模原样的放在当前文件的包含位置. include& ...

  4. NVMe SSD是什么?

    https://blog.51cto.com/alanwu/1766945 一直对闪存存储关注的朋友对NVMe SSD一定非常熟悉,NVMe SSD是现如今性能最好的存储盘.这种高性能盘在互联网领域已 ...

  5. Java虚拟机解析篇之---垃圾回收器

    上一篇说了虚拟机的内存模型,在说到堆内存的时候我们提到了,堆内存是Java内存中区域最大的一部分,而且垃圾回收器主要就是回收这部分的内容.那么这篇就来介绍一下垃圾回收器的原理以及回收的算法. Java ...

  6. 巴厘岛的雕塑(sculptures)

    巴厘岛的雕塑(sculptures) 印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道. 在这条主干道上一共有 N 座雕塑,为方便起见,我们把这些雕塑从 1 到 N 连续地进行标号,其中第 i ...

  7. 重新学习MySQL数据库11:以Java的视角来聊聊SQL注入

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  8. P1476 休息中的小呆

    P1476 休息中的小呆 题目描述 当大家在考场中接受考验(折磨?)的时候,小呆正在悠闲(欠扁)地玩一个叫“最初梦想”的游戏.游戏描述的是一个叫pass的有志少年在不同的时空穿越对抗传说中的大魔王ch ...

  9. 业务基类对象BaseBLL

    using System; using System.Collections; using System.Data; using System.Text; using System.Collectio ...

  10. (转)Adaboost

    基本原理 Adaboost算法基本原理就是将多个弱分类器(弱分类器一般选用单层决策树)进行合理的结合,使其成为一个强分类器. Adaboost采用迭代的思想,每次迭代只训练一个弱分类器,训练好的弱分类 ...