2018.8.4 正睿暑期集训营 Day1

时间:4.5h(实际)

期望得分:30+50+30

实际得分:30+50+30(菜啊)

比赛链接

A 数对子

题目链接

\(Solution\)

  考虑两个数异或怎么会得到1:\(0\oplus0=0,0\oplus1=1,1\oplus1=0\),也就是同一位的两个1会抵消成0。那么令\(bit[x]\)表示\(x\)的二进制1的个数,如果计算奇偶性,\(bit[x\oplus y]\%2=(bit[x]+bit[y])\%2\)。因为如果有变成0的1也一定是两个一起变成0。那么如果令\(p_0\)表示区间\([l,r]\)中\(bit[i]\)为偶数的\(i\)的个数,\(p_1\)表示区间中\(bit[i]\)为奇数的\(i\)的个数,该区间的答案为\(p_0\times p_1\)。

  计算\(p_0\),可以数位DP。\(p_0[l,r]=p_0[r]-p_0[l-1]\),考虑\([0,m]\)中的\(p_0\)怎么求。对于一个偶数\(x\),\(bit[x]\)一定与\(bit[x+1]\)奇偶性相反。于是我们这样分组:\(01,23,45\ldots\)奇偶性是这样的:\(偶奇,奇偶,奇偶,偶奇\ldots\)可得:$$p_0[0,m]=\begin{cases}\frac{m+1}{2},& m为奇数\\frac{m}{2}+\left[bit[m]是奇数\right],& m为偶数\end{cases}$$

  对于区间的处理,\(O(n^2)\):把端点离散化,这样把所有区间分成了若干段小区间,每段区间是若干段小区间的并。这样每有一段区间,直接去找属于它的区间即可。如图:

  \(O(n\log n)\):建一棵值域\(1\sim2^{32}-1\)的线段树,动态开点(能覆盖大区间就直接覆盖,否则递归新建左/右区间节点)。

  root没初始化为0,本地大样例都可过。。OJ上RE,调了很长时间。。(我干什么都RE有时候还能正常输出我也很无奈啊)

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 400000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=100005*17; char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{
#define lson son[x][0]
#define rson son[x][1]
int tot,son[N][2];
LL sum[N][2];
bool cover[N]; #define Query(l,r) (Calc(r)-Calc(l-1))
#define Update(x) sum[x][0]=sum[lson][0]+sum[rson][0], sum[x][1]=sum[lson][1]+sum[rson][1]
inline bool Check(LL x)
{
int res=0;
for(; x; x>>=1) res+=x&1;
return res&1;
}
inline LL Calc(LL x)
{
return (x>>1)+((x&1)||Check(x));//x&1?(x+1)>>1:(x>>1)+Check(x);
}
void Insert(int &x,LL l,LL r,LL L,LL R)
{
if(!x) x=++tot;
if(cover[x]) return;
if(L<=l && r<=R)
{
cover[x]=1;
sum[x][1]=Query(l,r), sum[x][0]=r-l+1-sum[x][1];
return;
}
LL m=l+r>>1;
if(L<=m) Insert(lson,l,m,L,R);
if(m<R) Insert(rson,m+1,r,L,R);
Update(x);
cover[x]=cover[x]||(cover[lson]&&cover[rson]);//!
}
}T; inline LL read()
{
LL now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
int n=read(),root=0;//root初始化为0!!!
for(LL l,lim=(1ll<<32)-1; n--; )
l=read(), T.Insert(root,1,lim,l,read()), printf("%lld\n",T.sum[root][0]*T.sum[root][1]); return 0;
}

B 逆序对

题目链接

容易看出决策位置单调。可靠这个分治。

但是有很简单的堆的贪心写法,没看懂。。


C 盖房子

题目链接


考试代码

A

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
typedef unsigned int uint;
const int N=1e5+5; int n,A[N];
uint L[N],R[N];
bool vis[1003]; inline uint read()
{
uint now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline bool Check(uint x)
{
int res=0;
for(; x; x>>=1) res+=x&1;
return res&1;
}
//void Make()
//{
// int n=read();
// for(int i=2; i<=n; ++i)
// for(int j=i+1; j<=3*n; ++j) if(Check(i^j)) printf("%d^%d=%d is OK\n",i,j,i^j);
//} int main()
{
// freopen(".in","r",stdin); // Make();
n=read();
for(uint i=1,li,ri; i<=n; ++i)
{
li=L[i]=read(), ri=R[i]=read(); memset(vis,0,sizeof vis);
int cnt=0;
for(int j=1; j<i; ++j)
for(uint k=L[j],r=R[j]; k<=r; ++k)
if(!vis[k]) A[++cnt]=k, vis[k]=1;
for(uint j=li; j<=ri; ++j)
if(!vis[j]) A[++cnt]=j, vis[j]=1; LL ans=0;
for(int j=1; j<cnt; ++j)
for(int k=j+1; k<=cnt; ++k)
ans+=Check(A[j]^A[k]);
printf("%lld\n",ans);
}
return 0;
}

B

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 400000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define Vec std::vector<int>
typedef long long LL;
const int N=2e5+5; int n,cnt,B[N];
LL Ans;
char IN[MAXIN],*SS=IN,*TT=IN;
struct BIT
{
#define lb(x) (x&-x)
int n,val[N];
inline void Clear()
{
memset(val,0,sizeof val);
}
inline void Add(int p,int v)
{
if(!p) return;
for(; p<=n; p+=lb(p)) val[p]+=v;
}
inline LL Query(int p)
{
LL res=0;
for(; p; p^=lb(p)) res+=val[p];
return res;
}
}T1,T2; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline LL Query(int p,int v)
{
return p-T1.Query(v)+T2.Query(v);
}
inline int Check(int p,int x)
{
LL r1=Query(p,x),r2=r1;
int res=p,bef=p;
while(p<cnt)
{
++p;
if(B[p]<x) --r2;
else if(B[p]>x) ++r2;
if(r2<r1) r1=r2, res=p;
}
for(int i=bef+1; i<=res; ++i) T1.Add(B[i],1), T2.Add(B[i],-1);
return Ans+=r1, res;
}
inline int Check2(int p,int x,int lim)
{
LL r1=Query(p,x),r2=r1;
int res=p,bef=p;
while(p<lim)
{
++p;
if(B[p]<x) --r2;
else if(B[p]>x) ++r2;
if(r2<r1) r1=r2, res=p;
}
for(int i=bef+1; i<=res; ++i) T1.Add(B[i],1), T2.Add(B[i],-1);
return Ans+=r1, res;
} int main()
{
// freopen("B2.in","r",stdin); T1.n=T2.n=n=read(), cnt=n>>1;
for(int i=1; i<=cnt; ++i) T2.Add(B[i]=read(),1);
for(int i=1; i<=cnt; ++i) Ans+=i-1-T1.Query(B[i]), T1.Add(B[i],1);
T1.Clear();
if(n<=5000)
for(int i=1,p=0; i<n; i+=2) p=Check(p,i);
else
for(int i=1,p=0,len=15000000/n; i<n; i+=2) p=Check2(p,i,std::min(i+len,cnt));
printf("%lld\n",Ans); return 0;
}

C

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define mod (10007)
#define Mod(x) (x>=mod&&(x-=mod))
const int N=36; int n,K,X[N],Y[N];
bool ban[N][N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
namespace Subtask1
{
int A[N];
inline bool Ck1(int *a)
{
for(int i=1; i<=n; ++i) if(a[i]==i) return 1;
return 0;
}
inline bool Ck2(int *a)
{
for(int i=1; i<=n; ++i) if(a[i]==n-i+1) return 1;
return 0;
}
inline int Check(int *a)
{
for(int i=1; i<=n; ++i) if(ban[i][a[i]]) return 0;
if(!Ck1(a)) return 0;
if(!Ck2(a)) return 0;
return 1;
}
inline bool End(int *a)
{
for(int i=1; i<=n; ++i) if(a[i]!=i) return 0;
return 1;
}
void Main()
{
for(int i=1; i<=n; ++i) A[i]=i;
int res=0;
do{
res+=Check(A), std::next_permutation(A+1,A+1+n);
}while(!End(A));
printf("%d\n",res%mod);
}
}
namespace Subtask2
{
int Ans,fac[N];
bool vis[N];
void DFS(int x,int n,bool f1,bool f2)
{
if(x>n) {Ans+=(f1&&f2); return;}
if(f1&&f2) {Ans+=fac[n-x+1], Ans>=mod&&(Ans-=mod); return;}
for(int i=1; i<=n; ++i)
if(!vis[i]) vis[i]=1, DFS(x+1,n,f1||(x==i),f2||(x+i==n+1)), vis[i]=0;
}
void Main()
{
fac[0]=1;
for(int i=1; i<=n; ++i)
{
fac[i]=fac[i-1]*i;
while(fac[i]>=mod) fac[i]-=mod;
}
DFS(1,n,0,0);
printf("%d\n",Ans%mod);
}
}
namespace Subtask3
{
int f[2][(1<<18)+3][2][2];
void Main()
{
int lim=(1<<n)-1, now=1, las=0;
f[0][0][0][0]=1;
for(int i=0; i<n; ++i)
{
for(int s=0; s<=lim; ++s)
{
for(int j=0,ss; j<n; ++j)
{
if(s>>j&1) continue;
if(ban[i+1][j+1]) continue;
ss=s|(1<<j);
f[now][ss][i==j][i+j==n-1]+=f[las][s][0][0], Mod(f[now][ss][i==j][i+j==n-1]);
f[now][ss][i==j][1]+=f[las][s][0][1], Mod(f[now][ss][i==j][1]);
f[now][ss][1][i+j==n-1]+=f[las][s][1][0], Mod(f[now][ss][1][i+j==n-1]);
f[now][ss][1][1]+=f[las][s][1][1], Mod(f[now][ss][1][1]);
}
}
now^=1, las^=1;
}
printf("%d\n",f[las][lim][1][1]);
}
} int main()
{
// freopen(".in","r",stdin); n=read(), K=read();
for(int i=1; i<=K; ++i) ban[X[i]=read()][Y[i]=read()]=1;
if(n<=10 && !K) return Subtask2::Main(),0;
if(n<=10) return Subtask1::Main(),0;
if(n<=18) return Subtask3::Main(),0;
if(!K && n<=25)
{
if(n==19) printf("4551\n");
else if(n==20) printf("7535\n");
else if(n==21) printf("5570\n");
else if(n==22) printf("2328\n");
else if(n==23) printf("4809\n");
else if(n==24) printf("8690\n");
else if(n==25) printf("5330\n");
// else if(n==26) printf("\n");
// else if(n==27) printf("\n");
// else if(n==28) printf("\n");
}
else putchar('0'); return 0;
}

8.4 正睿暑期集训营 Day1的更多相关文章

  1. 8.10 正睿暑期集训营 Day7

    目录 2018.8.10 正睿暑期集训营 Day7 总结 A 花园(思路) B 归来(Tarjan 拓扑) C 机场(凸函数 点分治) 考试代码 A B C 2018.8.10 正睿暑期集训营 Day ...

  2. 8.6 正睿暑期集训营 Day3

    目录 2018.8.6 正睿暑期集训营 Day3 A 亵渎(DP) B 绕口令(KMP) C 最远点(LCT) 考试代码 A B C 2018.8.6 正睿暑期集训营 Day3 时间:5h(实际) 期 ...

  3. 8.9 正睿暑期集训营 Day6

    目录 2018.8.9 正睿暑期集训营 Day6 A 萌新拆塔(状压DP) B 奇迹暖暖 C 风花雪月(DP) 考试代码 A B C 2018.8.9 正睿暑期集训营 Day6 时间:2.5h(实际) ...

  4. 8.8 正睿暑期集训营 Day5

    目录 2018.8.8 正睿暑期集训营 Day5 总结 A 友谊巨轮(线段树 动态开点) B 璀璨光滑 C 构解巨树 考试代码 A B C 2018.8.8 正睿暑期集训营 Day5 时间:3.5h( ...

  5. 8.7 正睿暑期集训营 Day4

    目录 2018.8.7 正睿暑期集训营 Day4 A 世界杯(贪心) B 数组(线段树) C 淘汰赛 考试代码 A B C 2018.8.7 正睿暑期集训营 Day4 时间:5h(实际) 期望得分:. ...

  6. 8.5 正睿暑期集训营 Day2

    目录 2018.8.5 正睿暑期集训营 Day2 总结 A.占领地区(前缀和) B.配对(组合) C 导数卷积(NTT) 考试代码 T1 T2 T3 2018.8.5 正睿暑期集训营 Day2 时间: ...

  7. 7.30 正睿暑期集训营 A班训练赛

    目录 2018.7.30 正睿暑期集训营 A班训练赛 T1 A.蔡老板分果子(Hash) T2 B.蔡老板送外卖(并查集 最小生成树) T3 C.蔡老板学数学(DP NTT) 考试代码 T2 T3 2 ...

  8. 8.9 正睿暑期集训营 Day6 C 风花雪月(DP)

    题目链接 完整比赛在这儿. 杜老师tql . 求期望要抽卡的次数,也就是求期望经历了多少不满足状态.而每个不满足的状态对答案的贡献为\(1\),所以可以直接算概率.即\(Ans=\sum_{不满足状态 ...

  9. 正睿暑期培训day1考试

    链接 A 理解一下题意,然后玩几组样例就能发现,实际上就是\(k\)个\(i\)等价于\(1\)个\(i-1\).所以就类似于\(k\)进制进行进位,如果最后\(0\)位上不是\(0\),那么就存在划 ...

随机推荐

  1. ceilometer主要组件分析

    一.Agent 主要有compute agent 和central agent,还有一些其他的agent这里暂时不分析. agent初始化时会动态加载给定namespace的pollster插件,并通 ...

  2. 《Linux命令行与shell脚本编程大全》 第五章理解shell

    5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序. 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动. 不过还有另外一个默认的shell是/bin/ ...

  3. 【BZOJ】1095: [ZJOI2007]Hide 捉迷藏 括号序列+线段树

    [题目]BZOJ 1095 [题意]给定n个黑白点的树,初始全为黑点,Q次操作翻转一个点的颜色,或询问最远的两个黑点的距离,\(n \leq 10^5,Q \leq 5*10^5\). [算法]括号序 ...

  4. 用MFC(C++)实现拼音搜索

    2015年4月1日更新: 我在github开源了Objective-C版的拼音搜索项目,感兴趣的可以去看看: OC版拼音搜索 最近项目需要实现按照拼音搜索资源.在网上找了一下,这方面的东西太少了. J ...

  5. 第6月第10天 svn checkout sqlite3

    1. http://www.cnblogs.com/xuling/p/5602036.html 2. http://blog.csdn.net/qq_26819733/article/details/ ...

  6. input文本框禁止修改文本——disabled和readonly属性的作用及区别

    1.input文本框禁止修改文本 disabled属性:<input type="text" name="name" value="xxx&qu ...

  7. 用代码截图去理解MVC原理

    [概述] 看了蒋金楠先生的<Asp.Net Mvc框架揭密>,这本书详细地讲解了mvc的原理,很深奥也很复杂,看了几遍才将就明白了一点.他在第一章用了一个他自己写的mvc框架作为例子,代码 ...

  8. RPM Database

    RPM Database RPM 不仅在安装.升级.卸载方面工作出色,而且在查询和验证方面也表现非凡.你很久前安装了一个数据库软件,但现在忘记了它的版本号,也不知道它的说明文档的位置,可以通过 RPM ...

  9. malloc 函数详解

    很多学过C的人对malloc都不是很了解,知道使用malloc要加头文件,知道malloc是分配一块连续的内存,知道和free函数是一起用的.但是但是: 一部分人还是将:malloc当作系统所提供的或 ...

  10. casperjs get开头的几个dom操作使用

    getCurrentUrl() Signature: getCurrentUrl() Retrieves current page URL. Note that the url will be url ...