A,B,C就不说了,又被D题卡住了.....

感觉怎么说呢,就是题解中的三个提示都已经想到了,就是不知道该怎么解决....

D. Integers Have Friends

简述题意:题目要求你找一个区间\([l,r]\)使得\(a_l\)%m=\(a_{l+1}\)%m=...=\(a_r\)%m。且m>=2,要求能找到的最大区间是多少。

看到取模我的想法就是将其最原本的式子写\(a_l\)=c1m+k,\(a_{l+1}\)=c2m+k,...,\(a_r\)=cn*m+k,考虑他们之间的关系,发现有个相同的余数k,我们做个差分数组,这样他们的k就都抵消了..于是我们惊奇的发现m是他们差分数组的gcd,这样后我们就知道一个区间合法当且仅当这个区间的差分数组的gcd>=2,这样的话我们直接在原数组上做差分。长度变为n-1,题目转化成,我们需要找到一个区间,使得他们的gcd>=2,且长度最大。.....

昨天到这就gg了....找区间的话,无外乎就是固定左端点最最远的右端点,尺取法等操作,考虑尺取法的话确实发现右端点是单调递增的,但左端点移动时我们无法去除左端点的影响,这个方法暂时告歇...接着考虑我们学过的一些数据结构,gcd符合区间加法的原则(广义上的区间加法,即知道了左区间的gcd,右区间的gcd,我们就可以计算出整个区间的gcd了)。这样的话我们就可以用各种结构进行优化试试,首先我们右端点是朴素的从左向右扫的,倍增能不能呢?好像可以,只需要预处理一下就可以了。线段树作为区间之王,行不行?貌似也可以,比如说给定一个l,我们先进入l这个叶子节点,等回溯时,一点点尝试将区间往上叠加,先将右区间全部叠加上看行不行,不行的话再向下搜寻就大概可以了(我码一下试试.).

倍增+ST表

//不等,不问,不犹豫,不回头.
#include
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define RE register
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair
#define PII pair
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(RE int x=y;x<=z;++x)
#define fep(x,y,z) for(RE int x=y;x>=z;--x)
#define go(x) for(RE int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=2e5+10;
int n;
ll a[N],b[N],f[N][22];//f[i][j]表示从第i个数开始,一共2^j个数的gcd的值. inline ll read()

{

ll x=0,ff=1;

char ch=getchar();

while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}

while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}

return x*ff;

} inline ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
int main()

{

// freopen("1.in","r",stdin);

int get(T);

while(T--)

{

get(n);

rep(i,1,n) get(a[i]);

rep(i,1,n-1) b[i]=abs(a[i+1]-a[i]); //注意这里用绝对值,防止出现负数.

rep(i,1,n-1) f[i][0]=b[i];

rep(j,1,20)

rep(i,1,n-1)

{

if(i+(1<<j)-1>n-1) break;

f[i][j]=gcd(f[i][j-1],f[i+(1<<(j-1))][j-1]);

}

ll ans=1;

rep(i,1,n-1)//从i为起点开始向后找.

{

ll gcc=f[i][0],now=i+1;

if(gcc<2) continue;

fep(j,20,0)

{

if(now+(1<<j)-1>n-1) continue;

if(gcd(gcc,f[now][j])>=2)

{

gcc=gcd(gcc,f[now][j]);

now=now+(1<<j);

}

}

ans=max(ans,now-i+1);

}

put(ans);

}

return (0_0);

}

//以吾之血,铸吾最后的亡魂.

线段树由于有巨大的常数,就T掉了,不过打出来还是比较考验码力的...

线段树上二分

//不等,不问,不犹豫,不回头.
#include
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define RE register
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair
#define PII pair
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(RE int x=y;x<=z;++x)
#define fep(x,y,z) for(RE int x=y;x>=z;--x)
#define go(x) for(RE int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=2e5+10;
int n;
ll a[N],b[N];
struct Tree
{
int l,r;
ll dat;//存一个区间所有值得gcd.
#define l(p) t[p].l
#define r(p) t[p].r
#define d(p) t[p].dat
}t[N<<2]; inline ll read()

{

ll x=0,ff=1;

char ch=getchar();

while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}

while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}

return x*ff;

} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline void build(int p,int l,int r)

{

l(p)=l;r(p)=r;

if(l==r) {d(p)=b[l];return;}

int mid=l+r>>1;

build(ls,l,mid);

build(rs,mid+1,r);

d(p)=gcd(d(ls),d(rs));

} inline int ask(int p,int k,ll &v)

{

if(v0)

{

if(l(p)r(p))

{

v=d(p);

return l(p);

}

int mid=l(p)+r(p)>>1,id=0;

if(k<=mid) id=ask(ls,k,v);

else id=ask(rs,k,v);

if(idr(ls))

{

if(gcd(v,d(rs))>=2)

{

v=gcd(v,d(rs));

return r(rs);

}

else return ask(rs,k,v);

}

else return id;

}

else

{

if(gcd(v,d(p))>=2)

{

v=gcd(v,d(p));

return r(p);

}

else if(l(p)r(p)) return l(p)-1;

else if(gcd(v,d(ls))<2) return ask(ls,k,v);

else

{

v=gcd(v,d(ls));

return ask(rs,k,v);

}

}

}
int main()

{

// freopen("1.in","r",stdin);

int get(T);

while(T--)

{

get(n);

rep(i,1,n) get(a[i]);

rep(i,1,n-1) b[i]=abs(a[i+1]-a[i]);

if(n-1>=1) build(1,1,n-1);

ll ans=1;

rep(i,1,n-1)//枚举每一个左端点。

{

if(b[i]<2) continue;

ll v=0;

ll p=ask(1,i,v);

ans=max(ans,p-i+2);

}

putl(ans);

}

return 0;

}

//以吾之血,铸吾最后的亡魂.

E. The Three Little PigsE. The Three Little Pigs

我脑子有坑...还是读错题了,...每次袭击都一定会袭击x个...我以为每个方案都要袭击若干次...

既然如此那就好办了,我们可以枚举大灰狼在哪一分钟袭击了,然后在这一分钟选出x个就行了,具体来说对于一个询问x而言答案为\(\sum_{i=0}^{n} C_{3*i}^x\)

可这里有q个询问...怎么搞....一般来说,遇到这种数学式子的问题且是组合数,我们需要找到递推式来快速找到答案。因为组合数的种种优美性质,求多个组合数的和时总是能找到递推预处理,然后O(1)的输出答案。一般的我们可以考虑我们已经知道了当前数x的答案,我们思考怎么根据已有的数据快速得到x+1的答案,具体的我们令\(f(x,j)表示\sum_{i=1}^{n} C_{3*i+j}^{x}\),显然\(f(x,0)\)就是每个x的答案,由于\(C_{3*i+j}^{x}=C_{3*i+j-1}^{x}+C_{3*i+j-1}^{x-1}\)

所以有\(f(x,1)=f(x,0)+f(x-1,0)\)

\(f(x,2)=f(x,1)+f(x-1,1)\)

通过简单的容斥(一点都不简单...)发现\(f(x,0)+f(x,1)+f(x,2)=\sum_{i=1}^{n}C_{3*i+0}^{x}+\sum_{i=1}^{n}C_{3*i+1}^{x}+\sum_{i=1}^{n}C_{3*i+2}^{x}=\sum_{i=1}^{n}(C_{3*i+0}^{x}+C_{3*i+1}^{x}+C_{3*i+2}^{x})=\sum_{i=3}^{3*n+2} C_{i}^{x}\)

到这里就停止了吗?不,路还在前方,我们把式子展开一下试试:\(C_x^x+C_{x+1}^x+C_{x+2}^x+...+C_{3*n+2}^x\)我们可以发现\(C_x^x+C_{x+1}^x=C_{x+1}^{x+1}+C_{x+1}^x=C_{x+2}^{x+1}\)哇,这样可以一直合并下去啊!最后的结果呢,就是\(C_{3*n+3}^{x+1}\)

经过一番努力我们得到了\(f(x,0)+f(x,1)+f(x,2)=C_{3*n+3}^{x+1}\)

结合之上的两条\(f(x,1)=f(x,0)+f(x-1,0)\)

\(f(x,2)=f(x,1)+f(x-1,1)\)

我们找出递推式:\(f(x,0)=\frac{C_{3n+3}^{x+1}-f(x-1,1)-2*f(x-1,0)}{3}\)

\(f(x,1)=f(x,0)+f(x-1,0)\)

\(f(x,2)=f(x,1)+f(x-1,1)\)

初值\(f(0,0)=f(0,1)=f(0,2)=n+1\)

目标为\(ans(x)=f(x,0)\)经过离线就可以O(n)解决问题了。

最后来个总结:题目要求\(\sum_{i=0}^{n} C_{3*i}^{x}\)的值,我们肯定不能直接求,显然要利用组合数的一些公式进行化简,但观察组合数的x是不变的,变化的是3*i,我们一方面可以想到他们都是相差3的,我们可以将其中的1,2补齐变成连续的,一方面可以思考组合数的化简公式\(C_n^m=C_{n-1}^{m-1}+C_{n-1}^m\)可以发现下面的n都要变成n-1,这就提示我们要设出\(f(x,j)\)为\(\sum C_{3*i+j}^x\)这样的话我们就可以找到关系了。至于初值为什么要赋成n+1,i=0确实要考虑。

查看代码

//不等,不问,不犹豫,不回头.
#include
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair
#define PII pair
#define ull unsigned long long
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(RE int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=1e6+10,P=1e9+7;
int n,m;
ll jc[3*N],inv_jc[3*N],f[N*3][3]; inline int read()

{

int x=0,ff=1;

char ch=getchar();

while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}

while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}

return x*ff;

} inline ll power(ll a,int b)

{

ll ans=1;

while(b)

{

if(b&1) ans=ansa%P;

b>>=1;

a=a
a%P;

}

return ans%P;

} inline void prework()

{

jc[0]=1;inv_jc[0]=1;

int t=3n+3;

rep(i,1,t) jc[i]=jc[i-1]
i%P;

inv_jc[t]=power(jc[t],P-2);

fep(i,t-1,1) inv_jc[i]=inv_jc[i+1]*(i+1)%P;

} inline ll C(int n,int m)

{

if(m>n) return 0;

return jc[n]inv_jc[m]%Pinv_jc[n-m]%P;

}
int main()

{

//freopen("1.in","r",stdin);

get(n);get(m);prework();

f[0][0]=f[0][1]=f[0][2]=n+1;

ll inp=power(3,P-2);

rep(i,1,3n)

{

f[i][0]=((C(3
n+3,i+1)-f[i-1][1]-2f[i-1][0])%P+P)%Pinp%P;

f[i][1]=(f[i][0]+f[i-1][0])%P;

f[i][2]=(f[i][1]+f[i-1][1])%P;

}

rep(i,1,m)

{

int get(x);

putl(f[x][0]);

}

return (0_0);

}

//以吾之血,铸吾最后的亡魂.

PS:此题卡常,请将常数尽可能的减小,当处理1-n的阶乘及逆元时,可以先将n的阶乘的逆元求出来,之后就可以O(n)的预处理逆元了。

Codeforces Round #736 (Div. 2)的更多相关文章

  1. Codeforces Round #366 (Div. 2) ABC

    Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...

  2. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

  3. Codeforces Round #368 (Div. 2)

    直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...

  4. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

  5. Codeforces Round #279 (Div. 2) ABCDE

    Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems     # Name     A Team Olympiad standard input/outpu ...

  6. Codeforces Round #262 (Div. 2) 1003

    Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...

  7. Codeforces Round #262 (Div. 2) 1004

    Codeforces Round #262 (Div. 2) 1004 D. Little Victor and Set time limit per test 1 second memory lim ...

  8. Codeforces Round #371 (Div. 1)

    A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给 ...

  9. Codeforces Round #268 (Div. 2) ABCD

    CF469 Codeforces Round #268 (Div. 2) http://codeforces.com/contest/469 开学了,时间少,水题就不写题解了,不水的题也不写这么详细了 ...

随机推荐

  1. 动态规划精讲(一)LC 最长递增子序列的个数

    最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7]输出: 2解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, ...

  2. 【PHP数据结构】链表的相关逻辑操作

    链表的操作相对顺序表(数组)来说就复杂了许多.因为 PHP 确实已经为我们解决了很多数组操作上的问题,所以我们可以很方便的操作数组,也就不用为数组定义很多的逻辑操作.比如在 C 中,数组是有长度限制的 ...

  3. php后台解决跨域

    protected function _initalize() { header("content-type:text/html;charset=utf-8"); header(& ...

  4. 《如何进行接口mock测试》

    前言: Mock通常是指:在测试一个对象时,我们构造一些假的对象来模拟与其交互.而这些Mock对象的行为是我们事先设定且符合预期.通过这些Mock对象来测试对象在正常逻辑,异常逻辑或压力情况下工作是否 ...

  5. 如何通过云效Flow完成自动化部署—主机部署

    如何通过云效Flow完成自动化部署-主机部署,云效流水线Flow是持续交付的载体,通过构建自动化.集成自动化.验证自动化.部署自动化,完成从开发到上线过程的持续交付.通过持续向团队提供及时反馈,让交付 ...

  6. P4716-[模板]最小树形图

    正题 题目链接:https://www.luogu.com.cn/problem/P4716 题目大意 给出\(n\)个点\(m\)条边的一张有向图,求以\(r\)为根的最小外向树. \(1\leq ...

  7. 【MySQL】MySQL进阶(外键约束、多表查询、视图、备份与恢复)

    约束 外键约束 外键约束概念 让表和表之间产生关系,从而保证数据的准确性! 建表时添加外键约束 为什么要有外键约束 -- 创建db2数据库 CREATE DATABASE db2; -- 使用db2数 ...

  8. CSS3思维导图

  9. Python读取网页表格数据

    学会了从网格爬取数据,就可以告别从网站一页一页复制表格数据的时代了. 说个亲身经历的事: 以前我的本科毕业论文是关于"燃放烟花爆竹和空气质量"之间关系的,就要从环保局官网查资料. ...

  10. Data Management Tools(数据管理工具)《一》

    数据管理工具 1.LAS数据集 # Process: LAS 数据集统计数据 arcpy.LasDatasetStatistics_management("", "SKI ...