传送门

\(A\)

找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来

typedef long long ll;
int n,a,b;ll res;
int main(){
scanf("%d%d%d",&n,&a,&b);
if(a>b||n==1&&a!=b)return puts("0"),0;
res=(a+b+1ll*(n-2)*b)-(a+b+1ll*(n-2)*a)+1;
printf("%lld\n",res);
return 0;
}

\(B\)

分别算出需要走一次的对数和两次的对数即可

typedef long long ll;
const int N=1e5+5;
char s[N];int n;ll res,sum;
int main(){
scanf("%s",s+1),n=strlen(s+1);
fp(i,1,n)sum+=(s[i]=='U'?n-i:i-1);
res=(1ll*n*(n-1)-sum)*2+sum;
printf("%lld\n",res);
return 0;
}

\(C\)

不难发现蓝点构成了一个类似树的东西,那么连通块个数就是总点数减去边数,分别维护一下就好了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=2005;
char mp[N][N];int r[N][N],c[N][N],s[N][N],n,m,q;
inline int qs(R int x,R int y,R int xx,R int yy){
return s[xx][yy]-s[x-1][yy]-s[xx][y-1]+s[x-1][y-1];
}
inline int qr(R int x,R int y,R int xx,R int yy){
return r[xx][yy]-r[x-1][yy]-r[xx][y-1]+r[x-1][y-1];
}
inline int qc(R int x,R int y,R int xx,R int yy){
return c[xx][yy]-c[x-1][yy]-c[xx][y-1]+c[x-1][y-1];
}
int main(){
scanf("%d%d%d",&n,&m,&q);
fp(i,1,n){
scanf("%s",mp[i]+1);
fp(j,1,m)s[i][j]=(mp[i][j]=='1')+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
fp(i,1,n)fp(j,1,m-1){
r[i][j]=r[i-1][j]+r[i][j-1]-r[i-1][j-1]+(mp[i][j]=='1'&&mp[i][j+1]=='1');
}
fp(i,1,n-1)fp(j,1,m){
c[i][j]=c[i-1][j]+c[i][j-1]-c[i-1][j-1]+(mp[i][j]=='1'&&mp[i+1][j]=='1');
}
for(R int x,y,xx,yy;q;--q){
scanf("%d%d%d%d",&x,&y,&xx,&yy);
printf("%d\n",qs(x,y,xx,yy)-qr(x,y,xx,yy-1)-qc(x,y,xx-1,yy));
}
return 0;
}

\(D\)

首先如果\(A=B\)答案为\(1\),所以我们假设\(B>A\)

找到第一个\(A,B\)二进制意义下不同的位\(r\),那么前面的位都是没有用的可以删掉

然后我们把数分成两个集合\(X:[A,2^r),Y:[2^r,B]\)

设\(k\)为\(B\)中第一个小于\(r\)且为\(1\)的二进制位,则有

  • 只用\(X\)能表示出\([A,2^r)\)(直接选对应的数),且只能表示出这些(能表示出的最小的数为\(A\),最大的数为\(2^r-1\))

  • 只用\(Y\)能且只能表示出\([2^r,2^r+2^{k+1}-1]\)(因为每一个\(2^r+2^i\)(i\leq k)都必定存在于\(Y\)中)

  • 同时用\(X\)和\(Y\)能表示出\([2^r+A,2^{r+1}-1]\)(直接选\(2^r\)和一个\(X\)中的数),且只能表示出这些(同上)

那么我们直接加上\([A,2^{r+1}-1]\),然后判一下\(2^r+2^{k+1}-1\)和\(2^r+A\)的大小就好了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
ll a,b,res;
int main(){
scanf("%lld%lld",&a,&b);
if(a==b)return puts("1"),0;
R int r,k;
for(r=59;(a>>r&1)==(b>>r&1);--r);
a&=(1ll<<(r+1))-1,b&=(1ll<<(r+1))-1;
res=(1ll<<(r+1))-a;
for(k=r-1;(~k)&&(b>>k&1^1);--k);
if(a>(1ll<<(k+1)))res-=a-(1ll<<(k+1));
printf("%lld\n",res);
return 0;
}

\(E\)

我应该就是那种数据结构做傻了的人……

先说一下题解的做法再说我的吧

首先当时间足够久之后,所有数的相对顺序肯定是按\(v\)排序之后的相对顺序,记\(id_i\)表示按\(v\)排序之后\(i\)处在的位置

我们假设一开始时只有\(i\)是被选中的,那么对于一个\(x_j<x_i\)且\(v_j>v_i\)的点\(j\),肯定会经过\(i\)使得自己被选中,而且按\(v\)排序之后所有在\(i,j\)之间的点都会被选中

我们对于每一个\(i\),计算出最大的\(id_j\)且\(x_j<x_i\),记为\(r_i\),那么所有\([id_i,id_{r_i}]\)之间的点都会被选。同理可定义\(l_i\)。容易发现\(l,r\)都是单调不降的

那么问题转化成给定\(n\)个区间且保证左右端点单调不降,选择其中若干个使得覆盖\([1,n]\),那么我们记\(f_i\)表示\([1,i]\)都已经被覆盖的方案数,前缀和优化转移即可

我的做法在后面

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=2e5+5;
struct node{
int x,v;
inline bool operator <(const node &b)const{return x<b.x;}
}a[N];
int id[N],l[N],r[N],f[N],n;
inline bool cmp(const int &x,const int &y){return a[x].v<a[y].v;}
int main(){
scanf("%d",&n);
fp(i,1,n)scanf("%d%d",&a[i].x,&a[i].v),id[i]=i;
sort(a+1,a+1+n),sort(id+1,id+1+n,cmp);
fp(i,1,n)l[id[i]]=r[id[i]]=i;
fp(i,2,n)cmax(r[i],r[i-1]);
fd(i,n-1,1)cmin(l[i],l[i+1]);
f[0]=1;
for(R int i=1,j=0,sum=1;i<=n;++i){
while(j<l[i]-1)sum=dec(sum,f[j++]);
upd(f[r[i]],sum),upd(sum,sum);
}
printf("%d\n",f[n]);
return 0;
}

首先先按\(x\)排序,对于一个\(i\),如果它一开始被选就肯定会被选,否则设\(las\)和\(nxt\)分别为前一个被选的和后一个被选的,设\(l\)表示\([1,las]\)中所有速度的最大值,\(r\)表示\([nxt,n]\)中所有速度的最小值,那么\(i\)不会被选当且仅当\(i\in [l,r]\)(也就是说既不可能有数从前面赶上它导致它被选,它也不可能赶上一个后面的数导致自己被选)

我们设\(las_i\)表示当\(i\)选了之后,最大的\(j\)使得\(j\)被选之后\([j+1,i-1]\)这个区间内每一个数都会被选,那么可以二分,判断的时候在主席树上判一下就行了

然后设\(f[i]\)表示\(i\)必须选的方案数,那么上一个被选的可以是\([las[i],i-1]\)中的任意一个数,前缀和优化一下就好了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
inline int max(R int x,R int y){return x>y?x:y;}
inline int min(R int x,R int y){return x<y?x:y;}
const int N=2e5+5,M=N*35,inf=0x3f3f3f3f;
int ls[M],rs[M],sz[M],rt[N],nd;
void ins(int &p,int q,int l,int r,int x){
p=++nd,ls[p]=ls[q],rs[p]=rs[q],sz[p]=sz[q]+1;
if(l==r)return;int mid=(l+r)>>1;
x<=mid?ins(ls[p],ls[q],l,mid,x):ins(rs[p],rs[q],mid+1,r,x);
}
int query(int p,int q,int l,int r,int ql,int qr){
if(!(sz[p]-sz[q])||ql<=l&&qr>=r)return sz[p]-sz[q];
int mid=(l+r)>>1,res=0;
if(ql<=mid&&query(ls[p],ls[q],l,mid,ql,qr))return 1;
if(qr>mid&&query(rs[p],rs[q],mid+1,r,ql,qr))return 1;
return 0;
}
struct node{
int x,v;
inline bool operator <(const node &b)const{return x<b.x;}
}a[N];
int b[N],las[N],f[N],mx[N],mn[N],sum[N];
int n;
inline int find(R int pos){
R int l=0,r=pos-1,ans=pos-1,mid;
while(l<=r){
mid=(l+r)>>1;
if(mid==pos-1||mx[mid]+1>mn[pos]-1||!query(rt[pos-1],rt[mid],1,n,mx[mid]+1,mn[pos]-1))
ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
fp(i,1,n)scanf("%d%d",&a[i].x,&a[i].v),b[i]=a[i].v;
sort(a+1,a+1+n),sort(b+1,b+1+n);
fp(i,1,n){
a[i].v=lower_bound(b+1,b+1+n,a[i].v)-b;
ins(rt[i],rt[i-1],1,n,a[i].v);
}
mx[0]=0;fp(i,1,n)mx[i]=max(mx[i-1],a[i].v);
mn[n+1]=inf;fd(i,n,1)mn[i]=min(mn[i+1],a[i].v);
fp(i,1,n+1)las[i]=find(i);
f[0]=sum[0]=1;
fp(i,1,n+1){
f[i]=dec(sum[i-1],(las[i]?sum[las[i]-1]:0));
sum[i]=add(sum[i-1],f[i]);
}
printf("%d\n",f[n+1]);
return 0;
}

\(F\)

神仙结论题

以下设\(f(x,y)\)表示\(x,y\)辗转相除的步数且默认\(x<y\)

首先我们考虑斐波那契数列,并定义\(F[0]=F[1]=1\),容易发现\(f(F[i],F[i+1])=i\)且对于所有\(f(a,b)=i\),有\(a\geq F[i],b\geq F[i+1]\)。所以第一个问题很简单就能搞出来

我们定义一个数对\(f(a,b)\)是好的,当且仅当不存在\(c<a,d<b\)且\(f(c,d)>f(a,b)\),那么只有好的数对会对答案有贡献

我们定义一个数对\(f(a,b)\)是优秀的,当且仅当若\(f(a,b)=k\),则\(a,b\leq F[k+2]+F[k-1]\)

有一个结论:任何一个好的数对经过一次辗转相除之后会变成一个优秀的数对

考虑反证法,假设\(a=y,b=py+x\),且\(f(a,b)=k+1\),那么辗转相除之后变成\((x,y)\),如果\((x,y)\)不是优秀的数对,则\(y>F[k+2]+F[k-1]\),从而有

\[\begin{aligned}
&a=y>F[k+2]\\
&x>F[k]\\
&b=py+x\geq y+x>F[k+2]+F[k-1]+F[k]=F[k+3]\\
\end{aligned}
\]

所以存在\(c=F[k+2],d=F[k+3]\),使得\(f(c,d)>f(a,b)\),这与\((a,b)\)是好的数对不符

这样我们就证明了任意一个好的数对经过一次辗转相除之后会变成一个优秀的数对,而优秀的数对并不会太多(据说满足\(f(a,b)=k\)的优秀的数对个数是\(O(k)\)?不过我并不会证明)

那么我们打表把所有\(f(a,b)=k\)的优秀的数对打出来就好了,询问的时候用优秀的数对去生成好的数对即可

//quming
#include<bits/stdc++.h>
#define R register
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
typedef long long ll;
const int N=105,M=90;
struct node{
ll x,y;
inline node(R ll xx,R ll yy):x(xx),y(yy){}
};vector<node>g[N];
ll f[N],n,m,T,res,cnt;
int main(){
f[0]=f[1]=1;fp(i,2,M)f[i]=f[i-1]+f[i-2];
g[1].pb(node(1,2)),g[1].pb(node(1,3)),g[1].pb(node(1,4));
fp(i,1,M-3){
for(auto v:g[i]){
R ll x=v.y,y=v.x+x;
while(y<=f[i+3]+f[i])g[i+1].pb(node(x,y)),y+=x;
}
}
scanf("%lld",&T);
while(T--){
scanf("%lld%lld",&n,&m);if(n>m)swap(n,m);
for(cnt=1;f[cnt+1]<=n&&f[cnt+2]<=m;++cnt);
if(cnt==1){printf("%lld %lld\n",cnt,n*m%P);continue;}
res=0;
for(auto v:g[cnt-1]){
R ll x=v.x,y=v.y;
if(y<=n)res+=(m-x)/y%P;
if(y<=m)res+=(n-x)/y%P;
res%=P;
}
printf("%lld %lld\n",cnt,res);
}
return 0;
}

AtCoder Grand Contest 015题解的更多相关文章

  1. AtCoder Grand Contest 015 题解

    A - A+...+B Problem 常识 Problem Statement Snuke has N integers. Among them, the smallest is A, and th ...

  2. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

  3. AtCoder Grand Contest 015 C - Nuske vs Phantom Thnook

    题目传送门:https://agc015.contest.atcoder.jp/tasks/agc015_c 题目大意: 现有一个\(N×M\)的矩阵\(S\),若\(S_{i,j}=1\),则该处为 ...

  4. AtCoder Grand Contest 015 E - Mr.Aoki Incubator

    题目传送门:https://agc015.contest.atcoder.jp/tasks/agc015_e 题目大意: 数轴上有\(N\)个点,每个点初始时在位置\(X_i\),以\(V_i\)的速 ...

  5. Atcoder Grand Contest 015 F - Kenus the Ancient Greek(找性质+乱搞)

    洛谷题面传送门 & Atcoder 题面传送门 一道难度 Au 的 AGC F,虽然看过题解之后感觉并不复杂,但放在现场确实挺有挑战性的. 首先第一问很简单,只要每次尽量让"辗转相除 ...

  6. Atcoder Grand Contest 054 题解

    那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...

  7. AtCoder Grand Contest 015

    传送门 A - A+...+B Problem 题意:n个数最大值a,最小值b,求和的可能数量. #include<cstdio> #include<algorithm> us ...

  8. AtCoder Grand Contest 030题解

    第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...

  9. AtCoder Grand Contest 031题解

    题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...

随机推荐

  1. [高清] Java编程思想第四版完整中文高清版

    ------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...

  2. The three day 给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本

    """ 给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本. 所谓无效化 IP 地址,其实就是用 "[.]" 代替了每个 ...

  3. c# 获取网页的爬虫程序

    转载于:https://www.cnblogs.com/wzk153/p/9145684.html HtmlAgilityPack相关详解: https://www.cnblogs.com/asxin ...

  4. (转)数据库函数解析JSON字符串

    一.返回单行单列 二.返回表 三.SQL206版本开始支持 SELECT * FROM OPENJSON(@JsonStr)

  5. Java任务调度框架Quartz教程

    一.什么是quartz作业调度? Quartz框架是一个全功能.开源的任务调度服务,可以集成几乎任何的java应用程序—从小的单片机系统到大型的电子商务系统.Quartz可以执行上千上万的任务调度. ...

  6. StatusStrip控件的使用(转:http://blog.sina.com.cn/s/blog_4f18c3ec0100fguf.html)

    c# winForm 将窗体状态栏StatusStrip 分成左中右三部分 右边显示当前时间 实现效果: 通过StatusStrip显示窗体状态栏 同时将状态栏分成三部分 居左边显示相关文字信息 中间 ...

  7. js校验规则--去空格、加空格

    为了更加直观,有些号码需要加空格: // 拼接空格,每4位加一个空格 let bankAccount = '6228888888888888888'; let blank_value = bankAc ...

  8. JAVA - Windows下JDK默认安装的配置参数

    JDK版本1.8 JAVA_HOME C:\Program Files\Java\jdk1.8.0_60 CLASSPATH .;%%JAVA_HOME%%\lib;%%JAVA_HOME%%\lib ...

  9. 用weexplus从0到1写一个app(2)-页面跳转和文章列表及文章详情的编写

    说明 结束连续几天的加班,最近的项目终于告一段落,今天抽点时间开始继续写我这篇拖了很久的<用weexplus从0到1写一个app>系列文章.写这篇文章的时候,weexplus的作者已经把w ...

  10. SAP 2019 TechEd Key Note解读:云时代下SAP从业人员如何做二次开发?

    刚刚过去的在巴塞罗那举行的2019 SAP TechEd,SAP照例向全球广大的SAP生态圈从业者们传达了一些重要的信息,其中一条为:Building Extensions for the Intel ...