Postal Vans

题目大意

4*n的网格,要经过所有点的有向有环,不重复经过点的路径总数

n<=1000

题解

显然 插头dp

以4为切面

问题是,会发现 超精度

解决呢要么实现高精度,要么换python XD

c++实现 未+高精度,会爆掉

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--) using namespace std; const string filename = "vans"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} int n; const int S1001 = 0;
const int S1122 = 1;
const int S1100 = 2;
const int S0110 = 3;
const int S0011 = 4;
const int S1221 = 5;
const int S0000 = 6; long long dp[1010][10];
int s2[10][10]; void init(){
s2[S1001][S0000] = 1;
s2[S1001][S1100] = 1;
s2[S1001][S0110] = 1;
s2[S1001][S0011] = 1;
s2[S1001][S1221] = 1; s2[S1122][S1001] = 1;
s2[S1122][S1122] = 1;
// s2[S1122][S1100] = 1; 不应该自闭
// s2[S1122][S0011] = 1; 不应该自闭
// s2[S1122][S0000] = 1; 不应该自闭 s2[S1100][S1122] = 1;
s2[S1100][S1001] = 1; s2[S0110][S1001] = 1; s2[S0011][S1122] = 1;
s2[S0011][S1001] = 1; // s2[S1221][S1001] = 1; 不应该自闭
s2[S1221][S0000] = 1;
s2[S1221][S1100] = 1;
s2[S1221][S0011] = 1;
s2[S1221][S1221] = 1;
} int main(){
usefile();
init();
cin>>n; dp[0][S1001] = 1;
dp[0][S1122] = 1;
rep(i,1,n){
rep(stateS,0,6){
rep(stateE,0,7){
if(s2[stateS][stateE]){
dp[i][stateE]+=dp[i-1][stateS];
}
}
}
}
// rep(i,0,n){
// rep(state,0,7){
// cout<<dp[i][state]<<"\t";
// }
// cout<<endl;
// }
cout<<dp[n-1][S0000]*2<<endl;
return 0;
}

增加高精度

#include <bits/stdc++.h>
typedef long long ll;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back using namespace std; const string filename = "vans"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} class hpa{
int DIGITS = 100'000'000; // 08lld
vector<ll>vals;
public:
hpa(){
}
hpa(ll v){
vals.pb(v);
}
void print(){
if(vals.size() == 0){
printf("0");
return;
}
printf("%lld",vals[vals.size()-1]);
per(i,0,vals.size()-1){
printf("%08lld",vals[i]);
}
}
hpa operator +(const hpa &another) const {
hpa ret;
rep(i,0,vals.size()){
ret.vals.pb(vals[i]);
}
rep(i,0,another.vals.size()){
if(i >= ret.vals.size()){
ret.vals.pb(another.vals[i]);
}else{
ret.vals[i]+=another.vals[i];
if(ret.vals[i] >= DIGITS){
if(i == ret.vals.size()-1){
ret.vals.pb(0);
}
ret.vals[i+1]+=ret.vals[i]/DIGITS;
ret.vals[i]%=DIGITS;
}
}
}
return ret;
}
}; int n; const int S1001 = 0;
const int S1122 = 1;
const int S1100 = 2;
const int S0110 = 3;
const int S0011 = 4;
const int S1221 = 5;
const int S0000 = 6; hpa dp[1010][10];
int s2[10][10]; void init(){
s2[S1001][S0000] = 1;
s2[S1001][S1100] = 1;
s2[S1001][S0110] = 1;
s2[S1001][S0011] = 1;
s2[S1001][S1221] = 1; s2[S1122][S1001] = 1;
s2[S1122][S1122] = 1;
// s2[S1122][S1100] = 1; 不应该自闭
// s2[S1122][S0011] = 1; 不应该自闭
// s2[S1122][S0000] = 1; 不应该自闭 s2[S1100][S1122] = 1;
s2[S1100][S1001] = 1; s2[S0110][S1001] = 1; s2[S0011][S1122] = 1;
s2[S0011][S1001] = 1; // s2[S1221][S1001] = 1; 不应该自闭
s2[S1221][S0000] = 1;
s2[S1221][S1100] = 1;
s2[S1221][S0011] = 1;
s2[S1221][S1221] = 1;
} int main(){
usefile();
init();
cin>>n; dp[0][S1001] = 2;
dp[0][S1122] = 2;
rep(i,1,n){
rep(stateS,0,6){
rep(stateE,0,7){
if(s2[stateS][stateE]){
dp[i][stateE]=(dp[i][stateE]+dp[i-1][stateS]);
}
}
}
}
// rep(i,0,n){
// rep(state,0,7){
// cout<<dp[i][state]<<"\t";
// }
// cout<<endl;
// }
dp[n-1][S0000].print();
printf("\n");
return 0;
}

A Rectangular Barn

Mircea Pasoi -- 2003

题目大意

(<=3000)*(<=3000)的矩阵

上面有<=30000 个坏点

求 最大不含坏点的矩形面积

题解

因为求的是最大矩形,那么它的四周要么是边界,要么是坏点

证明:反证明

如果存在一条边既没有邻接 边界,也没有邻接坏点。

那么对该边延伸 ,可以得到更大的矩形,矛盾

观察到这个性质后

我们考虑对任意 点(i,j)

i0<i,其中(i0,j)为距离(i,j)最远的点 且 线段(i0->i,j)上无坏点

线(i0->i,j)为高,做横向扩张,找左右两侧的最近的坏点 或边界,则有以(i,j)搜寻的矩形面积=(i0->i,j) * 该线段左右扩张的最大宽度

  1. 这样找到的矩形 一定是 合法矩形 所以这样找到的矩形面积小于等于 最大面积
  2. 这样一定能找到最大的矩形,因为我们证明了最大矩形 一定邻接着坏点或边界,那么该最大矩形上方边界所对应的 坏点,正下方的的点 在运算过程会计算到

所以O(3000*3000),以所有点计算出一个矩形,每个矩形计算复杂度为O(1),即可

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--) using namespace std; const string filename = "rectbarn"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} int L[3010],R[3010]; // j列当前线段 左右扩展的可行最远距离
int H[3010]; // j列 当前 的线段长度
bool g[3010][3010];
int n,m,ans;
int main(){
usefile();
freopen("rectbarn.in","r",stdin);
freopen("rectbarn.out","w",stdout);
int k;
cin>>n>>m>>k;
while(k--){
int i,j;
scanf("%d%d",&i,&j);
g[i][j]=1;
}
rep(j,0,m+1){
H[j]=0;
L[j]=1;
R[j]=m;
}
rep(i,1,n+1){
// 处理所有 坏点
rep(j,1,m+1){
if(g[i][j]){
H[j]=0;
L[j]=1;
R[j]=m;
}
}
// 计算所有 左侧 和 右侧 最远
int lm = 1;
rep(j,1,m+1){
if(!g[i][j]){
H[j]++;
L[j]=max(L[j],lm);
} else{
lm=j+1;
}
}
int rm = m;
per(j,1,m+1){
if(!g[i][j]){
R[j]=min(R[j],rm);
}else{
rm=j-1;
}
}
// 计算面积
rep(j,1,m+1){
if(!g[i][j]){
ans=max(ans,(R[j]-L[j]+1)*H[j]);
}
}
}
printf("%d\n",ans);
return 0;
}

Cow XOR

Adrian Vladu -- 2005

题目大意

n(<=100,000)个数,数值范围是[0,2^21 - 1]

求连续子区间 的最大xor值,输出 最大xor值,区间起始点,区间结束点

如果有多个区间满足最大异或,返回结束点index最小的,如果还有多个,返回长度最短的。

题解

首先

我们证明一下题目描述的结果唯一

如果多个 子区间 异或值相同,且结束点不同,那么 只有唯一可以选

如果两个 子区间 异或值相同,且结束点相同,那么 它们一定起始点不同,所以它们长度不同,只有最短可选

综上,题目描述结果唯一

然后

显然

xor[l->r] = xor[1->l-1]^xor[1->r]

所以 我们要找最大值,等于找两个前缀异或的最大值

从高位到低位,对所有前缀建立trie树,再for一遍贪心走trie树,贪心规则 有和当前位不同的走不同的路径,否则才走相同,(尽量在高位产生1)

空间 O(n*21),时间O(n*21)

空间节点数

s=0;
for i in range(0,22):
s+=min(2**i,100000)
print(s)

631071 个,然而 我开这么大会炸空间,开500000过的 (按道理讲 这样空间上看是开得有问题,开小了,不过过了测试)

我在实现过程中是找 区间左右端点靠的是 lower_bound二分,多用了空间,

然而,我们发现 最优区间必定有一个是 其前缀值的最小坐标

所以 如果枚举i去寻找 其期望的 前缀值对应的最小坐标,一定能找到最优值,可以优化

通过的,但空间开得不合理的代码,(我之前还用struct来写,虽然阅读上更好理解,但空间更加不够XD)

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--) using namespace std; const string filename = "cowxor"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} int n;
int a[100010];
int p[100010];
int ns[500010][2]; int nsi=0; int *root = ns[nsi++]; map<int,vector<int> > pv2idx; // 前缀异或 到 下表 void build(int idx){
int v = p[idx];
pv2idx[v].push_back(idx); // ordered
int * po = root;
per(i,1,21){
int bit = !!(v&(1<<i));
if(!po[bit]){
po[bit] = nsi++;
}
po=ns[po[bit]];
}
int bit = !!(v&1);
po[bit] = v;
} int query(int idx){
int v = p[idx];
int * po = root;
per(i,1,21){
int bit = !(v&(1<<i));
if(!po[bit]){
po = ns[po[bit^1]];
}else{
po = ns[po[bit]];
}
}
int bit = !(v&1);
return po[bit] == 0?po[bit^1]:po[bit];
} int ans=-1,ansl,ansr; void setAns(int v1,int l,int r){
// cout<<"SETANS:"<<v1<<" l:"<<l<<" r:"<<r<<endl;
if(l > r){
swap(l,r);
}
if(v1 < ans)return;
if(v1 > ans){
ans = v1;
ansl = l;
ansr = r;
return ;
}
if(r < ansr){
ansl = l;
ansr = r;
return ;
}
if(r > ansr){
return ;
}
if(l > ansl){
ansl = l;
return ;
}
} int main(){
usefile();
scanf("%d",&n);
rep(i,0,n){
scanf("%d",a+i);
}
rep(i,0,n){
p[i+1]=p[i]^a[i];
}
rep(i,0,n+1){
build(i);
}
// for(auto item:pv2idx){
// cout<<"--------"<<item.first<<endl;
// for(auto z:item.second){
// cout<<z<<"\t"<<endl;
// }
// cout<<endl;
// }
rep(i,0,n+1){
int ret = query(i);
int reti = lower_bound(pv2idx[ret].begin(),pv2idx[ret].end(),i)-pv2idx[ret].begin();
// cout<<"find:"<<i<<"["<<p[i]<<"]:"<<ret<<"("<<pv2idx[ret][reti]<<")"<<endl;
if(ret == p[i]){
if(i > 0){
setAns(ret^p[i],i-1,i);
}
}else if(reti > 0){
setAns(ret^p[i],i,pv2idx[ret][reti-1]);
}else{
setAns(ret^p[i],i,pv2idx[ret][reti]);
}
}
printf("%d %d %d\n",ans,ansl+1,ansr);
return 0;
}

USACO 6.1 章节的更多相关文章

  1. USACO 6.4 章节

    The Primes 题目大意 5*5矩阵,给定左上角 要所有行,列,从左向右看对角线为质数,没有前导零,且这些质数数位和相等(题目给和) 按字典序输出所有方案... 题解 看上去就是个 无脑暴搜 题 ...

  2. USACO 6.3 章节 你对搜索和剪枝一无所知QAQ

    emmm........很久很久以前 把6.2过了 所以emmmmmm 直接跳过 ,从6.1到6.3吧 Fence Rails 题目大意 N<=50个数A1,A2... 1023个数,每个数数值 ...

  3. USACO 5.5 章节

    Picture 题目大意 IOI 1998 求n (<=5000)个矩形 覆盖的图形 的周长(包括洞), 坐标范围[-10000,10000] 题解 一眼离散化+2维线段树,但仔细一想 空间不太 ...

  4. USACO 5.4 章节

    Canada Tour 题目大意 双向连通图,点从左向右排列, 你需要先从最左的点到最右的点,(过程中只能从左向右走) 然后再从最右的点返回最左的点,(过程中只能从右向左走) 过程中除了最左的点,其它 ...

  5. USACO 5.3 章节

    相关讲解可在USACO上看原文,也可以搜索nocow找到翻译的! (nocow上有些微翻译是有问题的,如果想看nocow翻译的建议也对着英文看) 以下记录以下 自己之前未掌握的一些要点,以及按自己的括 ...

  6. USACO 6.5 章节 世界上本没有龙 屠龙的人多了也便有了

    All Latin Squares 题目大意 n x n矩阵(n=2->7) 第一行1 2 3 4 5 ..N 每行每列,1-N各出现一次,求总方案数 题解 n最大为7 显然打表 写了个先数值后 ...

  7. (Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

    http://www.cnblogs.com/sxiszero/p/3618737.html 下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年 ...

  8. 算法竞赛入门经典+挑战编程+USACO

    下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...

  9. USACO . Your Ride Is Here

    Your Ride Is Here It is a well-known fact that behind every good comet is a UFO. These UFOs often co ...

随机推荐

  1. c3p0连接池在spring中的配置

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destr ...

  2. Java中的多线程基础

    1.线程与进程 进程: 进程是程序运行以及资源分配的基本单位,一个程序至少有一个进程. 如下图所示: 线程: 线程是CPU调度和分配的基本单位,一个进程至少有一个线程. 同一个进程中的线程共享进程资源 ...

  3. DP50题(转)

    转自https://www.luogu.org/blog/cccx2016/dp50-ti-ti-hao dp50题: poj1014 poj1015 poj1018 poj1036 poj1038 ...

  4. Vue2.0源码阅读笔记(四):nextTick

      在阅读 nextTick 的源码之前,要先弄明白 JS 执行环境运行机制,介绍 JS 执行环境的事件循环机制的文章很多,大部分都阐述的比较笼统,甚至有些文章说的是错误的,以下为个人理解,如有错误, ...

  5. JS 页面繁简字转换

    // 本js用于客户在网站页面选择繁体中文或简体中文显示,默认是正常显示,即简繁体同时显示// 在用户第一次访问网页时,会自动检测客户端语言进行操作并提示.此功能可关闭// 本程序只在UTF8编码下测 ...

  6. Linux Shell 脚本学习第一天: 使用grep 命令,lsusb, ps -ef, 实现树莓派(Debian OS)时检测到依赖的USB设备启动后,启动终端自动执行shell脚本

    1.应用背景: 无人监测的设备,常需要设置应用程序开机启动,程序启动前需要保证调用的设备先启动,运行环境先启动. 2.test.sh部分源码 #!/bin/sh #查看桌面是否启动 while tru ...

  7. Linux就该这么学07学习笔记

    参考链接:https://www.linuxprobe.com/chapter-07.html RAID磁盘冗余阵列 RAID 0 RAID 0技术把多块物理硬盘设备(至少两块)通过硬件或软件的方式串 ...

  8. Java虚拟机——Java内存区域与内存溢出

    内存区域 Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域.Java虚拟机规范将JVM所管理的内存分为以下几个运行时数据区:程序计数器.Java虚拟机栈.本地方法栈 ...

  9. (ACM模板)队列queue

    #include<iostream> #include<cstdio> #include<queue> using namespace std; struct po ...

  10. python如何获取变量的变量名

    假设现在存在一个值为1变量名为a的变量,如何通过一个函数获取该变量的变量名a? 上面这个需求来源于某群友的一个要求,希望能有一个这样的函数来方便打印. 这个需求很扯淡啊,为什么不用格式化输出?它回复到 ...