@shixinyi
        
        2018-01-04T12:46:34.000000Z
        字数 30368
        阅读 637
    OI
相当于%9,但是余0的是9。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
ll T,l,r;
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
ll cnt[20];
ll get_ans(ll x) {
if(x<=0) return x+1;
ll rs=1;//0
for(ll i=1;i<=9;++i) rs+=(cnt[i]=(x-i*i+i*9)/(i*9));//用循环简单一些
rs-=cnt[1]/8;
rs-=cnt[2]/7;
rs-=cnt[3]/2;
rs-=cnt[4]/5;
return rs;
}
int main() {
T=read();
while(T--) {
l=read();r=read();
printf("%lld\n",get_ans(r)-get_ans(l-1));
}
return 0;
}
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e4+10,maxm=4e5+10,INF=0x3f3f3f3f;//maxm开小了
int n,m,ans=INF;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[maxn],nxt[maxm],to[maxm],v[maxm],e=0;
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
}
int dis[maxn],zz[maxn];
bool vis[maxn];
int spfa(int st) {
int s=1,t=0,x,y,z,tot=1;
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[st]=0;vis[st]=1;zz[++t]=st;
while(tot--) {
x=zz[s];s=(s+1)%maxn;vis[x]=0;
for(y=fir[x];y;y=nxt[y]) {
if(dis[z=to[y]]<=dis[x]+v[y]||(x==st&&z==1)) continue;
dis[z]=dis[x]+v[y];
if(!vis[z]) {
vis[z]=1;tot++;
if(dis[z]<=dis[zz[s]]) {
s=(s-1+maxn)%maxn;
zz[s]=z;
}
else {
t=(t+1)%maxn;
zz[t]=z;
}
}
}
}
return dis[1];
}
int main() {
n=read(); m=read();
int x,y,z1,z2;
for(int i=1;i<=m;++i) {
x=read();y=read();
z1=read();z2=read();
if(x>y) swap(x,y),swap(z1,z2);
add(x,y,z1); add(y,x,z2);
}
for(y=fir[1];y;y=nxt[y]) ans=min(ans,spfa(to[y])+v[y]);
printf("%d",ans);
return 0;
}
正向跑一次,反向跑一次,求交点。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
const int maxn=8e5+10,INF=1e7;
int n,m,cse,tot1,tot2,p[maxn],tt,S,T,ok;
bool vis[2*maxn];
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Node{
int x,y,p;
}node[2*maxn];
bool cmp1(int a,int b) {
return node[a].x==node[b].x? node[a].y<node[b].y : node[a].x<node[b].x;
}
bool cmp2(int a,int b) {
return node[a].y==node[b].y? node[a].x<node[b].x : node[a].y<node[b].y;
}
int fir[4*maxn],nxt[4*maxn],to[4*maxn],e;
void add(int x,int y) {
// printf("add: %d %d\n",x,y);
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;
}
void init() {
tot1=read();tot2=read();tt=tot1+tot2;
S=tt*2+1;T=S+1;
for(int i=1;i<=tot1;++i) {
node[i].x=read();
node[i].y=read();
node[i].p=0;
}
for(int i=1;i<=tot2;++i) {
node[i+tot1].x=read();
node[i+tot1].y=read();
node[i+tot1].p=1;
}
node[S].x=1;node[S].y=0;
node[T].x=n;node[T].y=m+1;
}
void get_edge() {
for(int i=1;i<=tt;++i) p[i]=i;
sort(p+1,p+tt+1,cmp1);
for(int i=2;i<=tt;++i) if(node[p[i-1]].x==node[p[i]].x) add(p[i-1]+tt,p[i]);
if(node[p[1]].x==1) add(S,p[1]);
if(node[p[tt]].x==n) add(p[tt]+tt,T);
for(int i=1;i<=tt;++i) p[i]=i;
sort(p+1,p+tt+1,cmp2);
for(int i=2;i<=tt;++i) if(node[p[i-1]].y==node[p[i]].y)
add(p[i-1]+tt*(int)(node[p[i-1]].p==0),p[i]+tt*(int)(node[p[i]].p==1));
}
int get_d(int tox,int x) {
if(!x) return (tox+1)%4+1;
return 5-tox;
}
struct Line{
int x,y,z;
}li[5][2*maxn];
int tot[5];
//0~3
bool cmp3(const Line& a,const Line& b) {
return a.z==b.z? a.x<b.x:a.z<b.z;//写反了
}
void bld1(int x,int y,int p) {
p=(p-1)<<1;
if(x<S&&x>tt) x-=tt;
int ff=(node[x].y==node[y].y);
int s=(++tot[p+=ff]);
if(!ff) li[p][s].x=node[x].y,li[p][s].y=node[y].y,li[p][s].z=node[x].x;
else li[p][s].x=node[x].x,li[p][s].y=node[y].x,li[p][s].z=node[x].y;
}
void bld2(int x,int tox,int p) {
p=(p-1)<<1;
if(x<S&&x>tt) x-=tt;
int ff=tox/3;
int s=(++tot[p+=ff]);
if(!ff) li[p][s].z=node[x].x;
else li[p][s].z=node[x].y;
if(tox==1) li[p][s].x=node[x].y,li[p][s].y=m+1;
else if(tox==2) li[p][s].y=node[x].y,li[p][s].x=0;
else if(tox==3) li[p][s].y=node[x].x,li[p][s].x=0;
else li[p][s].x=node[x].x,li[p][s].y=n+1;
}
bool dfs(int pos,int tox,int p) {
vis[pos]=1;
int y,z,g,d,ok=0;
for(y=fir[pos];y;y=nxt[y]) {
if(vis[z=to[y]]) continue;
if((z==T&&p==1)||(z==S&&p==2)) return 1;
else if(z==T||z==S) {
ok=0; break;
}
ok=1; g=(z-1)%tt+1;d=get_d(tox,node[g].p);
bld1(pos,g,p);
if(dfs(z,d,p)) return 1;
}
vis[pos]=0;
if(!ok) bld2(pos,tox,p);
return 0;
}
set<ll> Gpl[2],Gmi[2];
set<ll>::iterator it1,it2;
int sz[3*maxn];
int q(int pos) {
int rs=0;
while(pos) {
rs+=sz[pos];
pos-=(pos&-pos);
}
return rs;
}
void chge(int pos,int x) {
while(pos<=m) {
sz[pos]+=x;
pos+=(pos&-pos);
}
}
int ans,ansx,ansy;
void rn(int x,int l,int r) {
int lx=l-1,rx=r,t=q(l-1),mid;
while(lx<rx-1) {
mid=(lx+rx)>>1;
if(q(mid)>t) rx=mid;
else lx=mid;
}
if(x<ansx||(x==ansx&&rx<ansy)) {
ansx=x;ansy=rx;
}
ok=1;
}
void get_ans() {
for(int i=0;i<4;++i) {
for(int j=1;j<=tot[i];++j) {
if(li[i][j].x>li[i][j].y) swap(li[i][j].x,li[i][j].y);
++li[i][j].x;--li[i][j].y;
if(li[i][j].x>li[i][j].y) li[i][j].z=INF;//z写的x
}
}
ans=0;
sort(li[0]+1,li[0]+tot[0]+1,cmp3);
sort(li[2]+1,li[2]+tot[2]+1,cmp3);
while(tot[0]&&li[0][tot[0]].z==INF) tot[0]--;
while(tot[2]&&li[2][tot[2]].z==INF) tot[2]--;
Gpl[0].clear();Gmi[0].clear();
Gpl[1].clear();Gmi[1].clear();//忘记clear
for(int i=1;i<4;i+=2) {
for(int j=1;j<=tot[i];++j) {
if(li[i][j].z==INF) continue;
Gpl[i>2].insert((ll)li[i][j].z+(ll)li[i][j].x*INF);
Gmi[i>2].insert((ll)li[i][j].z+(ll)(li[i][j].y+1)*INF);//应该以x或y为第一关键字
}
}
memset(sz,0,sizeof(sz));
int pos=1;it1=Gpl[1].begin();it2=Gmi[1].begin();
int l,r,now;ok=0;
for(int i=1;i<=n&&pos<=tot[0];++i) {
while(it1!=Gpl[1].end()&&(*it1)/(ll)INF==i) chge((*it1)%(ll)INF,1),it1++;
while(it2!=Gmi[1].end()&&(*it2)/(ll)INF==i) chge((*it2)%(ll)INF,-1),it2++;//ll
l=0;r=0;
while(pos<=tot[0]&&li[0][pos].z==i) {
l=max(l,li[0][pos].x);r=max(l-1,li[0][pos].y);
if(l<=r) {
ans+=(now=q(r)-q(l-1));
if(!ok&&now) rn(i,l,r);
}
l=r+1; pos++;
}
}
memset(sz,0,sizeof(sz));
pos=1;it1=Gpl[0].begin();it2=Gmi[0].begin(); ok=0;
for(int i=1;i<=n&&pos<=tot[2];++i) {
while(it1!=Gpl[0].end()&&(*it1)/(ll)INF==i) chge((*it1)%(ll)INF,1),it1++;
while(it2!=Gmi[0].end()&&(*it2)/(ll)INF==i) chge((*it2)%(ll)INF,-1),it2++;
l=0;r=0;
while(pos<=tot[2]&&li[2][pos].z==i) {
l=max(l,li[2][pos].x);r=max(l-1,li[2][pos].y);
if(l<=r) {
ans+=(now=q(r)-q(l-1));
if(!ok&&now) rn(i,l,r);
}
l=r+1; pos++;
}
}
}
void clear() {
memset(fir,0,sizeof(fir));
memset(nxt,0,sizeof(nxt));
memset(vis,0,sizeof(vis));
e=0;ansx=n+1;ansy=m+1;
tot[0]=tot[1]=tot[2]=tot[3]=0;
}
int main() {
while(scanf("%d%d",&n,&m)==2) {
printf("Case %d: ",++cse);
clear(); init();
get_edge();
if(dfs(S,1,1)||dfs(T,2,2)||(n==1&&!tot1&&!tot2)) printf("0");//n==1的情况直接射出去
else if(n==1) printf("impossible");
else {
get_ans();
if(ans) printf("%d %d %d",ans,ansx,ansy);
else printf("impossible");
}
printf("\n");
}
return 0;
}
直接枚举z,然后用并查集维护联通快,跑最短路。 
因为中间有一些已经连好的边,所以不能直接只判断从S所在联通块直接到T所在联通块的最短距离
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define ll long long
#define db double
const int maxn=400+10,maxm=5e4+10;
const db INF=1e17;
ll n,m,S,T,p[maxn],fa[maxn],h,now;
db d[maxn][maxn],ans=INF;
bool vis[maxn];
ll aa,ff;char cc;
ll read() {
aa=0;cc=getchar();ff=1;
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
struct Node{
ll x,y,z,k;int id;
}node[maxn];
bool cmp(const Node& a,const Node& b) {
return a.z < b.z;
}
db pf(db x) {return x*x;}
db get_dis(int a,int b) {
return sqrt(pf(node[a].x-node[b].x)+pf(node[a].y-node[b].y)+pf(node[a].z-node[b].z));
}
int fir[maxn],nxt[2*maxm],to[2*maxm],e=0;
void add(int x,int y) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;
}
int find(int x) {
return fa[x]==x? x:fa[x]=find(fa[x]);
}
struct Di{
int x,p;db d;
Di(){}
Di(int x,int p,db d):x(x),p(p),d(d){}
bool operator <(const Di& b) const{
return d > b.d;
}
};
priority_queue<Di> G;
db dis[maxn][2];
void get_ans(int pos) {
for(int i=1;i<=n;++i) dis[i][0]=dis[i][1]=INF;
dis[S][0]=0; G.push(Di(S,0,0));
int x,y,t; db rs=(db)now*0.5,ad,dx;//dx开成int
while(!G.empty()) {
x=G.top().x; t=G.top().p; dx=G.top().d; G.pop();//忘记pop
if(dx!=dis[x][t]) continue;
for(y=1;y<=pos;++y) {
if(find(y)!=find(S)&&find(y)!=find(T)) ad=(db)node[y].k*0.5;//忘记(db)
else ad=0;
if(d[x][y]==0) {
if(dis[y][0]<=dx+ad) continue;
dis[y][0]=dx+ad;
G.push(Di(y,0,dis[y][0]));
}
else if(node[y].k&&node[x].k>t&&dis[y][1]>dx+d[x][y]+ad-1) {//t与dx搞混
dis[y][1]=dx+d[x][y]+ad-1;
G.push(Di(y,1,dis[y][1]));
}
}
}
ans=min(ans,min(dis[T][0],dis[T][1])+rs);
}
int main() {
n=read();m=read();
for(int i=1;i<=n;++i) {
node[i].x=read();
node[i].y=read();
node[i].z=read();
node[i].k=read();
node[i].id=i;
}
sort(node+1,node+n+1,cmp);
for(int i=1;i<=n;++i) p[node[i].id]=i;
S=p[1];T=p[n];
h=max(node[S].z,node[T].z);
for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j)
d[i][j]=d[j][i]=get_dis(i,j);
for(int i=1;i<=n;++i) fa[i]=i;
int x,y;
for(int i=1;i<=m;++i) {
x=p[read()]; y=p[read()];
d[x][y]=d[y][x]=0;
add(x,y);
}
for(int i=1;i<=n;++i) {
for(int j=fir[i];j;j=nxt[j])
if(to[j]<i) fa[find(to[j])]=find(i);
for(int j=1;j<=i;++j) if(!vis[j]) {//上面的联通可能会导致下面的有些点与S、T联通
x=find(j);
if(x==find(S)||x==find(T)) {
now+=node[j].k; vis[j]=1;//j打成i
}
}
if(node[i].z<h||(i!=n&&node[i].z==node[i+1].z)) continue;
get_ans(i);
}
if(ans!=INF) printf("Case 1: %.4f",ans);
else printf("Case 1: impossible");
return 0;
}
计算几何题 
求能够构成的的个数,暴力代码:
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define db double
#define ll long long
const int maxn=2333+10;
const db eps=1e-11;
int n;
ll tot[3],ans;
int aa,ff;char cc;
int read() {
aa=0;ff=1;cc=getchar();
while(cc<'0'||cc>'9') {
if(cc=='-') ff=-1;//忘记判断负数情况
cc=getchar();
}
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa*ff;
}
struct Node {
db x,y;
}node[maxn];
db xx,yy,x2,y2;
db X_(int i,int j,int k) {
xx=node[j].x-node[i].x;x2=node[k].x-node[i].x;
yy=node[j].y-node[i].y;y2=node[k].y-node[i].y;
return xx*y2-yy*x2;
}
db D_(int i,int j,int k) {
xx=node[j].x-node[i].x;x2=node[k].x-node[i].x;
yy=node[j].y-node[i].y;y2=node[k].y-node[i].y;
return xx*x2+yy*y2;
}
int main() {
n=read();
for(int i=1;i<=n;++i) node[i].x=read(),node[i].y=read();
for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) {
tot[1]=tot[2]=0;
for(int k=1;k<=n;++k) if(k!=i&&k!=j) {
if(X_(i,j,k)+eps<0&&D_(i,j,k)+eps>=0) ++tot[1];
else if(X_(i,j,k)-eps>0&&D_(j,i,k)+eps>=0) ++tot[2];
}
ans+=tot[1]*tot[2];
}
printf("%lld",ans);
return 0;
}
cdq套cdq裸题
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=4e5+10;
int T,n,tot,qtot,ans[maxn/6];
int pz[maxn/4],tz;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int ef(int x) {
int l=1,r=tz,mid;
while(l<=r) {
mid=(l+r)>>1;
if(pz[mid]==x) return mid;
if(pz[mid]<x) l=mid+1;
else r=mid-1;
}
}
int xx[maxn],yy[maxn],zz[maxn],fnum[maxn];
struct Ask{
int qid,id;
}ask[maxn],ask1[maxn],ask2[maxn];
bool cmp(const Ask& a,const Ask& b) {
return xx[a.id]==xx[b.id]? a.id < b.id : xx[a.id] < xx[b.id];//相同时必须比较id否则会挂
}
bool cmp2(const Ask& a,const Ask& b) {
return yy[a.id]==yy[b.id]? a.id < b.id : yy[a.id] < yy[b.id];
}
void add(int x,int y,int z,int num) {
fnum[++tot]=num;ask[tot].id=tot;
xx[tot]=x;yy[tot]=y;zz[tot]=z;
if(num) ask[tot].qid=qtot;
}
int sz[maxn];
int q(int pos) {
int rs=0;
while(pos) {
rs+=sz[pos];
pos-=pos&-pos;
}
return rs;
}
void chge(int pos,int x) {
while(pos<=tz) {
sz[pos]+=x;
pos+=pos&-pos;
}
}
void cdq2(int l,int r) {
if(l>=r) return;
int mid=(l+r)>>1,now=0;
cdq2(l,mid); cdq2(mid+1,r);
for(int i=l;i<=mid;++i) if(!fnum[ask1[i].id]) ask2[++now]=ask1[i];
for(int i=mid+1;i<=r;++i) if(fnum[ask1[i].id]) ask2[++now]=ask1[i];
sort(ask2+1,ask2+now+1,cmp2);
for(int i=1;i<=now;++i) {
if(!fnum[ask2[i].id]) chge(zz[ask2[i].id],1);
else ans[ask2[i].qid]+=fnum[ask2[i].id]*q(zz[ask2[i].id]);
}
for(int i=1;i<=now;++i) if(!fnum[ask2[i].id]) chge(zz[ask2[i].id],-1);
}
void cdq(int l,int r) {
if(l>=r) return;
int mid=(l+r)>>1,now=0;
cdq(l,mid); cdq(mid+1,r);
for(register int i=l;i<=mid;++i) if(!fnum[ask[i].id]) ask1[++now]=ask[i];
for(register int i=mid+1;i<=r;++i) if(fnum[ask[i].id]) ask1[++now]=ask[i];
sort(ask1+1,ask1+now+1,cmp);
cdq2(1,now);
}
void clear() {
memset(ans,0,sizeof(ans));
tz=tot=qtot=0;
}
int main() {//提交的时候忘记关freopen
T=read();
int op,x,y,z,x1,y1,z1;
while(T--) {
n=read(); clear();
for(int i=1;i<=n;++i) {
op=read(); x=read(); y=read(); z=read();
if(op==1) add(x,y,z,0),pz[++tz]=z;
else {
x1=read();y1=read();z1=read();++qtot; pz[++tz]=z1; pz[++tz]=z-1;
add(x-1,y-1,z-1,-1); add(x1,y1,z1,1);
add(x1,y-1,z-1,1); add(x-1,y1,z-1,1); add(x-1,y-1,z1,1);
add(x-1,y1,z1,-1); add(x1,y-1,z1,-1); add(x1,y1,z-1,-1);//x、y、z需要-1
}
}
sort(pz+1,pz+tz+1);//忘记sort了
tz=unique(pz+1,pz+tz+1)-(pz+1);
for(int i=1;i<=tot;++i) zz[i]=ef(zz[i]);//提前离散化跑得更快
cdq(1,tot);
for(int i=1;i<=qtot;++i) printf("%d\n",ans[i]);
}
return 0;
}
一个裸的基环树+gcd 
需要注意一些细节问题.
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=1e5+10;
int n,m,hst;ll d;
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[maxn],nxt[2*maxn],to[2*maxn],e=1;ll v[2*maxn];
void add(int x,int y,ll z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=-z;
}
int zz[maxn],t,inh[maxn],vis[maxn];
void dfs1(int pos,int p) {
if(vis[pos]) {
while(t&&zz[t]!=pos) inh[zz[t--]]=1;
hst=pos; inh[pos]=1;
return ;//忘了return直接段错误
}
vis[pos]=1; zz[++t]=pos;
for(int y=fir[pos];y;y=nxt[y]) {
if(y==p) continue;
dfs1(to[y],y^1);
}
}
ll dis[maxn],toth,fa[maxn];
void dfs3(int pos,ll d,ll bel) {
dis[pos]=d;fa[pos]=bel;vis[pos]=1;
for(int y=fir[pos];y;y=nxt[y]) {
if(vis[to[y]]) continue;
dfs3(to[y],d+v[y],bel);
}
}
void dfs2(int pos,ll d,int p) {
dis[pos]=d;fa[pos]=pos;vis[pos]=1;
for(int y=fir[pos];y;y=nxt[y]) {
if(y==p) continue;
if(!inh[to[y]]) dfs3(to[y],v[y],pos);
else {
if(vis[to[y]]) {
if(to[y]==hst) toth=d+v[y];
continue;
}
inh[to[y]]=inh[pos]+1;
dfs2(to[y],d+v[y],y^1);
}
}
}
ll get_d(int x,int y) {
if(x==y) return 0;
if(inh[y]>inh[x]) return dis[y]-dis[x];
return -toth+(dis[y]-dis[x]);//正负号弄反
}
ll gcd(ll x,ll y) {
return y==0? x:gcd(y,x%y);
}
int main() {
n=read(); ll x,y,z,now;
for(int i=1;i<=n;++i) {
x=read(); y=read(); z=read();
add(x,y,z);
}
dfs1(1,0);
memset(vis,0,sizeof(vis));
dfs2(hst,0,0);
m=read();
for(int i=1;i<=m;++i) {
x=read();y=read();z=read();d=0;
if(fa[x]!=x) d-=dis[x];
if(fa[y]!=y) d+=dis[y];
d+=get_d(fa[x],fa[y]);
d%=z; now=toth%z;
if(d<=0) d+=z;
if(now<=0) now+=z;
now=gcd(now,z);
d%=now;if(!d) d+=now;
if((z-d)%now==0) printf("%lld\n",z-now);//必须特判否则挂
else printf("%lld\n",((z-d)/now)*now+d);
}
return 0;
}
Meet in the middle模板题 
因为是无向图,所以可以把从i点到其他点可以得到的二进制数的问题转化为从其他点到i点可以得到的二进制数,所以对于第二个dp就很好处理了. 
改题的时候T了一发
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=97,maxm=2e4+7,maxt=(1<<10)|3;//maxm开小了,T
int n,m,d,totans,sz1,sz2;
bool dp1[2][maxn][maxt],dp2[2][maxn][maxt];
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int fir[maxn],nxt[maxm],to[maxm],v[maxm],e=1;
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
to[++e]=x;nxt[e]=fir[y];fir[y]=e;v[e]=z;
}
bool vis[(1<<21)|5];int ans;
void get_ans(int x) {
if(!vis[x]) ++ans,vis[x]=1;
}
int main() {
n=read(); m=read(); d=read();
int x,y,z;
for(int i=1;i<=m;++i) {
x=read(); y=read(); z=read();
add(x,y,z);
}
sz1=d/2; sz2=d-sz1;
int p1=0,p2=0;
dp1[0][1][0]=1;
for(int s=1;s<=sz1;++s) {
p1^=1;
memset(dp1[p1],0,sizeof(dp1[p1]));
for(int t=0;t<(1<<s-1);++t) for(int i=1;i<=n;++i) {
if(dp1[p1^1][i][t]) for(int j=fir[i];j;j=nxt[j]) dp1[p1][to[j]][(t<<1)|v[j]]=1;
}
}
for(int i=1;i<=n;++i) dp2[0][i][0]=1;
for(int s=1;s<=sz2;++s) {
p2^=1;
memset(dp2[p2],0,sizeof(dp2[p2]));
for(int t=0;t<(1<<s-1);++t) for(int i=1;i<=n;++i) {
if(dp2[p2^1][i][t]) for(int j=fir[i];j;j=nxt[j]) dp2[p2][to[j]][(t<<1)|v[j]]=1;
}
}
for(int i=1;i<=n;++i) for(int t=0;t<(1<<sz1);++t) if(dp1[p1][i][t]) {
for(int tt=0;tt<(1<<sz2);++tt) if(dp2[p2][i][tt]) get_ans(t<<sz2|tt);
}
printf("%d\n",ans);
return 0;
}
一道sb题,但是场上sb了. 
改题的时候发现题解所说的单调队列并不需要. 
然后就自己随便搞了搞,跑得飞快(比std快3倍). 
写了两个版本的代码,分别debug,特别难受,后来,,, 
随便放一个跑得快的.
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=2000+7;
int n,m,k,up[maxn][maxn],down[maxn][maxn],ans,nowans[maxn][maxn],p[maxn];
bool ok[maxn][maxn];
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Ask{
int x,y;
}ask[maxn];
int f[maxn][maxn],g[maxn][maxn];
bool check(int x,int y,int t) {
if(t>m||t>n) return 0;
int l=y,r=y,pos1,pos2,now1,now2;
f[x][y]=up[x][y];g[x][y]=down[x][y];//一开始g也用的up赋值
now1=up[x][y]; now2=down[x][y];
while(now1+now2-1>=t&&l) {
l--;
now1=min(now1,up[x][l]);
now2=min(now2,down[x][l]);
f[x][l]=now1;g[x][l]=now2;
}
l++;
now1=up[x][y]; now2=down[x][y];
while(now1+now2-1>=t&&r<=m) {
r++;
now1=min(now1,up[x][r]);
now2=min(now2,down[x][r]);
f[x][r]=now1;g[x][r]=now2;
}
r--;
if(r-l+1<t) return 0;
pos1=l;
for(pos2=y;pos2<=r&&f[x][pos2]+g[x][pos2]-1>=t;++pos2) {
while(min(f[x][pos1],f[x][pos2])+min(g[x][pos1],g[x][pos2])-1<t) pos1++;
if(pos2-pos1+1>=t) return 1;
}
pos2=r;
for(pos1=y;pos1>=l&&f[x][pos1]+g[x][pos1]-1>=t;--pos1) {
while(min(f[x][pos1],f[x][pos2])+min(g[x][pos1],g[x][pos2])-1<t) pos2--;
if(pos2-pos1+1>=t) return 1;
}
return 0;
}
int main() {
n=read(); m=read(); k=read();
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) {
do cc=getchar();while(cc!='X'&&cc!='.');
if(cc=='X') ok[i][j]=1;
}
for(int i=1;i<=k;++i) {
ask[i].x=read(); ask[i].y=read();
ok[ask[i].x][ask[i].y]=1;
}
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) up[i][j]= ok[i][j]? 0 : up[i-1][j]+1;
for(int i=n;i;--i) for(int j=1;j<=m;++j) down[i][j]= ok[i][j]? 0 : down[i+1][j]+1;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) {
if(ok[i][j]) nowans[i][j]=0;
else nowans[i][j]=min(nowans[i-1][j-1],min(nowans[i-1][j],nowans[i][j-1]))+1;
ans=max(ans,nowans[i][j]);
}
p[k]=ans;
int x,y,l,r,len1,len2;
for(int qaq=k;qaq>1;--qaq) {
x=ask[qaq].x;y=ask[qaq].y;
ok[x][y]=0;
for(int i=x;i<=n&&!ok[i][y];++i) up[i][y]=up[i-1][y]+1;
for(int i=x;i&&!ok[i][y];--i) down[i][y]=down[i+1][y]+1;//曾把x和y弄错
while(check(x,y,ans+1)) ++ans;
p[qaq-1]=ans;
}
for(int i=1;i<=k;++i) printf("%d\n",p[i]);
return 0;
}
一道网络流解决可行流的问题,场上连了负边特别难受.
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const ll maxn=200+10,maxm=1000+10,INF=1e9;//数组开小了
ll n,m,S,T,ind[maxn];
ll ans;
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Node{
int x,y;ll cap,flow,w;
Node(){}
Node(int x,int y,ll cap,ll w):x(x),y(y),cap(cap),w(w){flow=0;}
}node[2*maxm];
int fir[maxn],nxt[2*maxm],e=1;
void add(int x,int y,ll z,ll w) {
node[++e]=Node(x,y,z,w); nxt[e]=fir[x]; fir[x]=e;
node[++e]=Node(y,x,0,-w); nxt[e]=fir[y];fir[y]=e;
}
ll zz[maxn],dis[maxn],from[maxn];
bool vis[maxn];
bool spfa() {
for(int i=1;i<=n+2;++i) dis[i]=INF,from[i]=0;//写成了i<=n
int s=1,t=0,x,y,z,o;
dis[S]=0; zz[++t]=S;vis[S]=1;
while(s<=t) {
x=zz[s%maxn];s++; vis[x]=0;
for(y=fir[x];y;y=nxt[y]) {
z=node[y].y;
if(node[y].flow>=node[y].cap||dis[z]<=dis[x]+node[y].w) continue;
dis[z]=dis[x]+node[y].w;
from[z]=y;
if(!vis[z]) {
vis[z]=1; t++;
zz[t%maxn]=z;
}
}
}
return dis[T]<INF;//一开始建负边的时候写的<0后来忘了改回来
}
ll MCMF() {
ll rs=0,now;
while(spfa()) {
now=INF;
for(int x=T;x!=S;x=node[from[x]].x) now=min(now,node[from[x]].cap-node[from[x]].flow);
for(int x=T;x!=S;x=node[from[x]].x) {
rs+=now*node[from[x]].w;
node[from[x]].flow+=now;
node[from[x]^1].flow-=now;
}
}
return rs;
}
int main() {
n=read(); m=read();
int x,y,f,c; S=n+1;T=n+2;
for(int i=1;i<=m;++i) {
x=read(); y=read(); c=read(); f=read();
ind[y]+=f; ind[x]-=f;
if(f<=c) {
add(y,x,f,1);
if(f!=c) add(x,y,c-f,1);
add(x,y,INF,2);
}
else {
ans+=f-c;
add(y,x,f-c,0);
add(y,x,c,1);
add(x,y,INF,2);
}
}
for(int i=1;i<=n;++i) {
if(ind[i]<0) add(i,T,-ind[i],0);
else if(ind[i]>0) add(S,i,ind[i],0);
}
add(n,1,INF,0);
ans+=MCMF();
printf("%lld",ans);
return 0;
}
逐渐明白样例是多么水的东西,对拍是多么优秀的东西
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=2e5+10;
int n,p1[maxn],p2[maxn],t1,t2;ll ans;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
int now[maxn];
struct Node{
int x,y,id;
}node[maxn];
bool cmp(const Node& a,const Node& b) {
return a.x < b.x;
}
bool cmp2(const Node& a,const Node& b) {
return now[a.y] < now[b.y];
}
int ef(int x,int *p,int r) {
int l=1,mid;
while(l<=r) {
mid=(l+r)>>1;
if(p[mid]==x) return mid;
if(p[mid]<x) l=mid+1;
else r=mid-1;
}
}
int zz[2][maxn];
int ef2(int x) {
int l=0,r=t1,mid;
if(node[zz[0][r]].x<x) return r+1;//一开始写特判t1=0的情况写错了
while(l<r-1) {
mid=(l+r)>>1;
if(node[zz[0][mid]].x>x) r=mid;//栈里面放的是标号而不是直接的x
else l=mid;
}
return r;
}
void add(int p,int x) {
if(!p) {
while(t1&&node[zz[0][t1]].y<=node[x].y) --t1;//栈里面放标号,按照y递减
zz[0][++t1]=x;
}
else {
while(t2&&node[zz[1][t2]].y>=node[x].y) --t2;
zz[1][++t2]=x;//++写成--了
if(t2>1) ans+=(ll)t1-(ll)ef2(node[zz[1][t2-1]].x)+1;
else ans+=t1;
}
}
void cdq(int l,int r) {
if(l==r) return; t1=0; t2=0;
int mid=(l+r)>>1,pos1=l,pos2=mid+1;
for(int i=l;i<=r;++i) {
if(node[i].y<=mid) add(0,i),now[node[i].y]=++pos1;
else add(1,i),now[node[i].y]=++pos2;
}
sort(node+l,node+r+1,cmp2);
cdq(l,mid); cdq(mid+1,r);
}
int main() {
freopen("scarecrows.in","r",stdin);
freopen("scarecrows.out","w",stdout);
n=read();
for(int i=1;i<=n;++i) {
p1[++t1]=node[i].x=read();
p2[++t2]=node[i].y=read();
}
sort(p1+1,p1+t1+1);
sort(p2+1,p2+t2+1);
for(int i=1;i<=n;++i) {
node[i].x=ef(node[i].x,p1,t1);
node[i].y=ef(node[i].y,p2,t2);
}
sort(node+1,node+n+1,cmp);
cdq(1,n);
printf("%lld",ans);
return 0;
}
一道数学题 
没什么好说的就是忘了取模,做题的时候一定要注意数据范围
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
ll T,p,n,m;
ll f[3],g[3][3],f2[3],g2[3][3];
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
ll gcd(ll x,ll y) {
return y==0? x:gcd(y,x%y);
}
void cf1() {
memcpy(f2,f,sizeof(f));
f[1]=f2[1]*g[1][1]%p+f2[2]*g[2][1]%p;
f[2]=f2[1]*g[1][2]%p+f2[2]*g[2][2]%p;
if(f[1]>=p) f[1]-=p;
if(f[2]>=p) f[2]-=p;
}
void cf2() {
memcpy(g2,g,sizeof(g));
memset(g,0,sizeof(g));
for(int i=1;i<=2;++i) for(int j=1;j<=2;++j) for(int k=1;k<=2;++k) {
g[i][j]+=g2[i][k]*g2[k][j]%p;
if(g[i][j]>=p) g[i][j]-=p;
}
}
void qpz(ll k) {
f[1]=f[2]=1; g[1][1]=0;
g[1][2]=g[2][1]=g[2][2]=1;
while(k) {
if(k&1) cf1();
cf2(); k>>=1;
}
}
ll qp(ll x,ll k) {
ll rs=1;
while(k) {
if(k&1) rs=rs*x%p;
k>>=1; x=x*x%p;
}
return rs;
}
void exgcd(ll a,ll b,ll &x,ll &y) {
if(!b) {
x=1; y=0;
return;
}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
ll get_ans(ll r,ll x,ll b) {
if(r<0) return 0;
ll rs=r/b;
if(r%b>=x) rs++;
return rs;
}
int main() {
freopen("1.in","r",stdin);
freopen("test.out","w",stdout);
T=read();ll x,y,a,b,c,o,l,r,w;
while(T--) {
w=read(); l=read(); r=read();
n=read(); p=read(); m=read();
qpz(n-3);
a=f[2]; b=p; c=(m%p-w%p*f[1]%p+p)%p;//
if(c%(o=gcd(a,b))) {
printf("0\n"); continue;
}
a/=o; b/=o; c/=o;
exgcd(a,b,x,y); x*=c;
x%=b; if(x<0) x+=b;
printf("%lld\n",get_ans(r,x,b)-get_ans(l-1,x,b));
}
fclose(stdin);fclose(stdout);
return 0;
}
/*
1
692858490132927148 33 93 11 90 52
*/
网络流题,给一些前缀和后缀,每个前缀或后缀都有一个代价,你需要用最小的代价覆盖所有的数字。 
先对前缀和后缀各建一个字典树,然后直接在字典树上建图跑最大流(最小割)。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=800+7,maxm=maxn*maxn,INF=0x3f3f3f3f;//
int n,m,a[maxn],len,S,T;
bool ok[maxn];
char c[23],s[23];
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
//////////////////////////////////////////////////////////////Dinic
struct Node{
int x,y,flow,cap;
Node(){}
Node(int x,int y,int cap):x(x),y(y),cap(cap){flow=0;}
}node[2*maxm];
int cur[maxn],fir[maxn],nxt[2*maxm],e=1;
int ind[maxn];
void add(int x,int y,int z) {
// printf("add: %d -> %d cap:%d\n",x,y,z);
node[++e]=Node(x,y,z); nxt[e]=fir[x];fir[x]=e;
node[++e]=Node(y,x,0); nxt[e]=fir[y];fir[y]=e;
}
int dis[maxn],zz[maxn];
bool BFS() {
memset(dis,-1,sizeof(dis));
int x,y,z,s=1,t=0;
zz[++t]=S; dis[S]=1;
while(s<=t) {
x=zz[s++];
for(y=fir[x];y;y=nxt[y]) {
if(dis[z=node[y].y]!=-1||node[y].flow>=node[y].cap) continue;
dis[z]=dis[x]+1;
zz[++t]=z;
}
}
return dis[T]!=-1;
}
int DFS(int pos,int maxf) {
if(pos==T||!maxf) return maxf;
int z,now,rs=0;
for(int &y=cur[pos];y&&maxf;y=nxt[y]) {
if(dis[z=node[y].y]!=dis[pos]+1||node[y].flow>=node[y].cap) continue;
now=DFS(z,min(maxf,node[y].cap-node[y].flow));
node[y].flow+=now;
node[y^1].flow-=now;
rs+=now; maxf-=now;
}
if(!rs) dis[pos]=-1;
return rs;
}
int Dinic() {
int rs=0;
while(BFS()) {
memcpy(cur,fir,sizeof(fir));
rs+=DFS(S,INF);
}
return rs;
}
////////////////////////////////////////////////////////////////
bool check(int r,int x,int p,int len) {
if(p==0) return (r>>(8-len))==x;
else {
r&=((1<<len)-1);
return r==x;
}
}
int le[maxn],num[maxn],cost[maxn];
int t[2]={1,1};
struct G{
int num,son[2];
}g[2][maxn*4];
void insert(int p,int x,int len,int i) {
int now=1,r;
if(!p) {
int xx=x; x=0;
for(int i=1;i<=len;++i,xx>>=1) {
x<<=1;
x+=(xx&1);
}
}
while(len--) {
r=x&1; x>>=1;
if(!g[p][now].son[r]) g[p][now].son[r]=++t[p];
now=g[p][now].son[r];
}
if(!g[p][now].num) g[p][now].num=i;
else if(cost[g[p][now].num] > cost[i]) g[p][now].num=i;
}
void dfs1(int pos,int f) {
if(!pos) return;
int id=g[0][pos].num;
if(id) add(f,n+id,cost[id]),f=id+n;//
dfs1(g[0][pos].son[0],f);
dfs1(g[0][pos].son[1],f);
if(id) {
for(int j=1;j<=n;++j) if((!ok[j])&&check(a[j],num[id],0,le[id])) {
ok[j]=1; add(n+id,j,INF);
}
}
}
void dfs2(int pos,int f) {
if(!pos) return;
int id=g[1][pos].num;
if(id) add(n+id,f,cost[id]),f=id+n;
dfs2(g[1][pos].son[0],f);
dfs2(g[1][pos].son[1],f);
if(id) {
for(int j=1;j<=n;++j) if((!ok[j])&&check(a[j],num[id],1,le[id])) {
ok[j]=1; add(j,n+id,INF);
}
}
}
int main() {
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
n=read(); m=read(); int x,p;
S=n+m+1; T=S+1;
memset(g,0,sizeof(g));
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=m;++i) {
scanf("%s%s",c+1,s+1);
cost[i]=read();
le[i]=len=strlen(s+1);
x=0; p= c[1]=='S';//0前缀 1后缀
for(int j=1;j<=len;++j) {
x<<=1;
x+=(s[j]-'0');
}
num[i]=x;
for(int j=1;j<=n;++j) if(check(a[j],x,p,len)) ok[j]=1;
insert(p,x,len,i);
}
for(int i=2;i<=n;++i) ok[1]&=ok[i];
if(!ok[1]) printf("-1");
else {
memset(ok,0,sizeof(ok));
dfs1(1,S);
for(int i=1;i<=n;++i) if(!ok[i]) add(S,i,INF);//一开始没有考虑到
memset(ok,0,sizeof(ok));
dfs2(1,T);
for(int i=1;i<=n;++i) if(!ok[i]) add(i,T,INF);
printf("%d\n",Dinic());
}
fclose(stdin); fclose(stdout);
return 0;
}
/*
8 7
0 1 2 3 4 5 6 6
P 000001 3
P 0000000 2
P 0000010 1
P 0000000 1
S 10 1
S 11 1
S 00 1
S 01 1
*/
一个模意义下开根的模板题。第一次写,还是debug了一个小时。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
ll T,n,p,ans;
ll f[3],g[3][3],f2[3],g2[3][3];
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
void cf1() {
memcpy(f2,f,sizeof(f));
f[1]=f2[1]*g[1][1]%p+f2[2]*g[2][1]%p;
f[2]=f2[1]*g[1][2]%p+f2[2]*g[2][2]%p;
if(f[1]>=p) f[1]-=p;
if(f[2]>=p) f[2]-=p;
}
void cf2() {
memcpy(g2,g,sizeof(g));
memset(g,0,sizeof(g));
for(int i=1;i<=2;++i) for(int j=1;j<=2;++j) for(int k=1;k<=2;++k) {
g[i][j]+=g2[i][k]*g2[k][j]%p;
if(g[i][j]>=p) g[i][j]-=p;
}
}
void qpz(ll k) {
f[1]=f[2]=1; g[1][1]=0;
g[1][2]=g[2][1]=g[2][2]=1;
while(k) {
if(k&1) cf1();
cf2(); k>>=1;
}
}
ll qp(ll x,ll k) {
ll rs=1;
while(k) {
if(k&1) rs=rs*x%p;
k>>=1; x=x*x%p;
}
return rs;
}
bool check(ll x) {
x%=p;
return qp(x,(p-1)>>1) == 1;
}
ll get_sq(ll x) {
ll a,wpf; x%=p;
do a=rand()%(2*p);while(!a||check(a*a-x));
wpf=(a*a-x)%p;
ll rs1=1,rs2=0,x1=a,x2=1,k=(p+1)>>1,aa,bb;//一开始x1写成了1
while(k) {
if(k&1) {
aa=(rs1*x1%p+rs2*x2%p*wpf%p)%p;
bb=(rs1*x2%p+rs2*x1%p)%p;
rs1=aa; rs2=bb;
}
k>>=1;
aa=(x1*x1%p+x2*x2%p*wpf%p)%p;
bb=2*x1*x2%p;
x1=aa; x2=bb;
}
return rs1;
}
int main() {
srand(1031); ll a,b;
T=read();
while(T--) {
a=read(); b=read(); n=read(); p=read();
if((!check(a)||(!check(b)))) printf("0\n");
else {
a=get_sq(a);
b=get_sq(b);
p--; qpz(n-1);
f[1]=f[1]*2%p; f[2]=f[2]*2%p;
p++; ans=(qp((a+b+p)%p,f[2])+qp((a-b+p)%p,f[2]))%p;
printf("%lld\n",ans*4%p);
}
}
return 0;
}
/*
4
2 3 1 10007
2 3 2 10007
2 3 3 10007
2 3 4 10007
*/
和去年省选D2T3很像,但不用本质不同,而且简单很多,用后缀数组和马拉车预处理lcp和以i为开头的回文串(放到树状数组里)bug弄了一晚上
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=16e5+10,INF=0x3f3f3f3f;
int n,m,Q,ql,qr;ll totans;
char A[maxn],B[maxn],S[2*maxn];
int x[maxn],y[maxn],c[maxn],sa[maxn],h[maxn],rad[maxn];
ll aa;char cc;
ll read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
ll minnum[4*maxn];
void bld(int pos,int l,int r) {
if(l==r) {
minnum[pos]=h[l];
return;
}
int mid=(l+r)>>1;
bld(pos<<1,l,mid); bld(pos<<1|1,mid+1,r);
minnum[pos]=min(minnum[pos<<1],minnum[pos<<1|1]);
}
ll qmin(int pos,int l,int r) {
if(l>=ql&&r<=qr) return minnum[pos];
int mid=(l+r)>>1;ll rs=INF;
if(ql<=mid) rs=min(rs,qmin(pos<<1,l,mid));
if(qr>mid) rs=min(rs,qmin(pos<<1|1,mid+1,r));
return rs;
}
ll tot[2][maxn],sum[2][maxn];
ll q(int pos,ll *sz) {
ll rs=0;
while(pos) {
rs+=sz[pos];
pos-=pos&-pos;
}
return rs;
}
void chge(int pos,int x,ll *sz,int n) {
while(pos<=n) {
sz[pos]+=x;
pos+=pos&-pos;
}
}
void get_sa(char *s,int n) {
int m='z'+1,p;
for(int i=0;i<n;++i) c[x[i]=s[i]]++;
for(int i=1;i<m;++i) c[i]+=c[i-1];
for(int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1) {
p=0;
for(int i=n-1;i>=n-k;--i) y[p++]=i;
for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<m;++i) c[i]=0;
for(int i=0;i<n;++i) c[x[y[i]]]++;
for(int i=1;i<m;++i) c[i]+=c[i-1];
for(int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
swap(x,y);p=1;
x[sa[0]]=0;
for(int i=1;i<n;++i)
x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&
((sa[i]+k<n&&sa[i-1]+k<n&&y[sa[i]+k]==y[sa[i-1]+k])||(sa[i]+k>=n&&sa[i-1]+k>=n))? p-1:p++;
if(p>=n) break; else m=p;
}
p=0;int u;
for(int i=0;i<n;++i) {
if(!x[i]) continue;
u=sa[x[i]-1];
if(p) p--;
while(s[u+p]==s[i+p]) p++;
h[x[i]]=p;
}
memset(minnum,0x3f3f3f3f,sizeof(minnum));
bld(1,1,n-1);
}
void manacher(char *s,ll *sz,int len,int o) {
int maxpos=0,p=0;
for(int i=len;i;--i) {//不是从0开始而是从1开始
s[i<<1]=s[i];
s[i<<1|1]='#';
}
s[0]=s[1]='#';
for(int i=2;i<=2*len;++i) {
if(maxpos>i) rad[i]=min(maxpos-i,rad[2*p-i]);
else rad[i]=0;
while(i-rad[i]>0&&i+rad[i]<=2*len+1&&s[i-rad[i]]==s[i+rad[i]]) rad[i]++;
rad[i]--;
if(i+rad[i]>maxpos) p=i,maxpos=i+rad[i];
}
for(int i=2;i<=2*len;++i) {
chge((i-rad[i]+1)>>1,1,tot[o],len);
chge((i+2)>>1,-1,tot[o],len);
}
}
int main() {
freopen("palindrome.in","r",stdin);
freopen("palindrome.out","w",stdout);
scanf("%s",A+1);
scanf("%s%s",A+1,B+1);
n=strlen(A+1); m=strlen(B+1);
for(int i=1;i<=m/2;++i) swap(B[i],B[m-i+1]);
for(int i=1;i<=n;++i) S[i-1]=A[i]; S[n]='#';//n不是n+1
for(int i=1;i<=m;++i) S[i+n]=B[i];
get_sa(S,n+m+1);
manacher(A,tot[0],n,0);
manacher(B,tot[1],m,1);
for(int i=1;i<=n;++i) chge(i,q(i,tot[0]),sum[0],n+1);
for(int i=1;i<=m;++i) chge(i,q(i,tot[1]),sum[1],m+1);
//注意是n+1和m+1,因为可能询问到
Q=read();int xx,yy,len;
for(int i=1;i<=Q;++i) {
xx=read(); yy=read();
ql=x[xx-1]; qr=x[yy+n];
if(qr<ql) swap(ql,qr);
++ql;
len=qmin(1,1,n+m);
totans=len;
totans+=q(xx+len,sum[0])-q(xx,sum[0]);
totans+=q(yy+len,sum[1])-q(yy,sum[1]);//注意边界
printf("%lld\n",totans);
}
fclose(stdin);fclose(stdout);
return 0;
}
/*
orzAchen
babaabbba
baaabbb
1
9 6
*/