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. Linux服务正常启动,Linux服务器能访问,但是外部机器不能访问

    公司用到了jenkins,就在自己虚拟机里面部署了一个jenkins.部署成功之后,在Linux虚拟机里面能正常访问,但是外部真实机却不能访问.当时的第一反应就是觉得应该是权限问题,猜测会不会是jen ...

  2. java_第一年_JavaWeb(9)

    JavaBean是一个遵循某种特定写法的Java类,有以下特点: 必需具有一个无参的构造函数 属性必需私有化 私有化的属性必需通过public类型的方法暴露给其它程序,其方法命名也有一定的规范 范例: ...

  3. 详解Twitter开源分布式自增ID算法snowflake(附演算验证过程)

    详解Twitter开源分布式自增ID算法snowflake,附演算验证过程 2017年01月22日 14:44:40 url: http://blog.csdn.net/li396864285/art ...

  4. JVM中类加载器的父委托机制

    类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器 ...

  5. 【学习总结】cpu缓存

    参考链接: cpu缓存java性能问题初探 高速缓存 在内存与cpu寄存器之间,还有一块区域叫做cpu高速缓存,即我们常常说的cache. cache分为L1.L2.L3三级缓存,速度递减,离cpu越 ...

  6. 20191108PHP数组查找练习

    <?php $arr=[20,30,60]; $new=array(22,"tom"=>33); echo $arr[2]; echo $new['tom']; for ...

  7. 在iOS中去掉input的光标

    在input上添加 readonly unselectable="on" οnfοcus="this.blur()" 就可以了.

  8. vue iview分页

    距离上次博客更新已经快一个月了,期间也有想法在空闲的时候更新几篇博文. 燃鹅,最近懒癌作祟,丢掉的东西越来越多,再不遏止的话就真成癌了. 趁着刚看完一篇心灵鸡汤,让打满鸡血的我总结下前段时间用到的iv ...

  9. git stash--在不想commit的情况下进行git pull

    公司的git开发模式是“主干发布,分支开发”,大多数情况下是多个开发在同一dev分支上进行开发,因此需要经常pull代码,如果本地工作区存在代码修改,那么pull肯定失败,提示需要先commit已修改 ...

  10. go语言从例子开始之Example38.排序

    Go 的 sort 包实现了内置和用户自定义数据类型的排序功能.我们首先关注内置数据类型的排序. Example: package main import ( "fmt" &quo ...