A
dp
B
以1号点为开头任意走走到不能走,再把路径倒过来以1号点为结尾开始再遍历到不能走
C
每个蚂蚁编号,相遇时掉头相当于继续走但是交换编号,每个蚂蚁最后的位置是可以知道的,因为编号的相对顺序是不会改变的,所以只要知道1号是哪个蚂蚁就能知道所有的编号在哪里
发现每有1只蚂蚁从l-1顺时针走到0,1号的位置就+1,从0走到l-1,1号的位置就-1
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 110000;
int n,L,T;
ll c;
ll p[maxn];
int main()
{
scanf("%d%d%d",&n,&L,&T);
c=0;
for(int i=1;i<=n;i++)
{
int x,w; scanf("%d%d",&x,&w);
if(w==1) p[i]=((ll)x+T)%L,c+=T/L+(T%L+x>=L?1:0);
else p[i]=((ll)x-T%L+L)%L,c-=T/L+(x-T%L<0?1:0);
}
sort(p+1,p+n+1); c=(c%n+n)%n;
c++;
for(int i=c;i<=n;i++) printf("%lld\n",p[i]);
for(int i=1;i<c;i++) printf("%lld\n",p[i]);
return 0;
}
D
因为n>=1,所以第一次操作一开始取的球可以是任意颜色,最后放球后取的球也可以是任意颜色,所以相当于计算n-1个未知颜色的球,每次放1红1蓝,再从中取2个球,求取出球的颜色序列数再*4
令N=n-1,设一开始有a个红球,N-a个蓝球,设操作i次后取了x个红球,有x<=a+i,2*i-x<=N-a+i,于是x-i<=a<=N+x-i,a对于所有i都成立,所以max(x-i)<=min(x-i)+N,考虑x-i的变化,取RR,x-i会+1,RBorBR,0, BB,-1
相当于在数轴上走,可以左右或不动,最右端-最左端<=N的走法数
(1:dp在[0,N]里任意走的方案ans1,但可能有重复,考虑一个max-min=A的方案,会被算N-A次(min有N-A种取值),所以再dp[0,N-1]里任意走的方案ans2,每个方案算N-A-1次,ans1-ans2就是答案
(2:也可以令出发点在0~N,强制0为最左端的点,要求右端点不超过N,用f[i][j][0/1]表示走i步后,在j,是否碰过0
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define __ %=Mod
using namespace std;
const ll Mod = 1e9+7;
const int maxn = 4100;
int n,m;
ll f[2][maxn];
ll solve(const int u)
{
int now=0; memset(f,0,sizeof f);
for(int i=0;i<=u;i++) f[now][i]=1ll;
for(int i=1;i<=m;i++)
{
now=!now;
for(int j=0;j<=u;j++)
{
f[now][j]=f[!now][j]*2ll%Mod;
if(j) (f[now][j]+=f[!now][j-1])__;
if(j<u) (f[now][j]+=f[!now][j+1])__;
}
}
ll re=0;
for(int i=0;i<=u;i++) (re+=f[now][i])__;
return re;
}
int main()
{
scanf("%d%d",&n,&m); n--; m--;
ll ans1=solve(n);
ll ans2=n?solve(n-1):0;
ans1=(ans1-ans2+Mod)%Mod;
printf("%lld\n",ans1*4ll%Mod);
return 0;
}
E
求所有方案正方形面积乘积和
构造一个东西使其方案数=原来的权值
正方形面积=边长平方=在边长内放1红1蓝2个球的方案数
问题变成了给若干个不能成为分界的点,求把一个区间分成若干段,每段放1红1蓝2球,所有的方案数
f[i][j]表示放了前i个格子,当前段已经有j个球的方案数,显然可以矩乘优化,Mlogn
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 110000;
const ll Mod = 1e9+7;
struct mat{ll a[3][3];mat(){memset(a,0,sizeof a);}}one,st,trans;
mat mul(mat &x,mat &y)
{
mat re;
for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++)
(re.a[i][k]+=x.a[i][j]*y.a[j][k]%Mod)%=Mod;
return re;
}
mat pw(mat x,int k)
{
mat re=one;
for(;k;k>>=1,x=mul(x,x)) if(k&1)
re=mul(re,x);
return re;
}
int n,m;
int main()
{
one.a[0][0]=one.a[1][1]=one.a[2][2]=1ll;
st.a[0][0]=1ll;
trans.a[0][0]=2ll,trans.a[0][1]=2ll,trans.a[0][2]=1ll;
trans.a[1][0]=1ll; trans.a[1][1]=1ll,trans.a[1][2]=1ll;
trans.a[2][0]=1ll,trans.a[2][1]=0ll,trans.a[2][2]=1ll;
scanf("%d%d",&m,&n); int las=0;
for(int i=1;i<=n;i++)
{
int p; scanf("%d",&p);
mat temp=pw(trans,p-las-1); las=p;
st=mul(st,temp);
trans.a[0][0]=1ll,trans.a[1][0]=0ll,trans.a[2][0]=0;
st=mul(st,trans);
trans.a[0][0]=2ll,trans.a[1][0]=1ll,trans.a[2][0]=1ll;
}
mat temp=pw(trans,m-las);
st=mul(st,temp);
printf("%lld\n",st.a[0][2]);
return 0;
}
F
将C排序后离散化到0~N,然后对于A,B将其变成i满足Ci-1< x<=Ci,在每个A处打+1标记,每个C处打-1标记,对于添加的卡牌,可以枚举用他的正/反面,在其位置+1,令pi=前i项的前缀和,若此时所有p>=0则存在合法匹配
否则我们执行若干次操作,每次操作将一个A变成B,相当于对p[B,A)区间+1,那么我们现在要求出对于所有的0<=x< N,要使得p0~x>=0,px+1~N>=-1,最少要操作多少次
我们先让所有的p>=-1,从右往左,遇到一个<-1的pi时,将覆盖他的区间按左端点从大到小操作(易证一定最优),然后从左往右,遇到一个-1时,同样贪心操作覆盖他的区间中右端点最大的
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1000000000
using namespace std;
const int maxn = 210000;
int n,m;
int A[maxn],B[maxn],C[maxn];
struct node{int x,i;};
inline bool operator <(const node x,const node y){return x.x<y.x;}
set<node>S;
set<node>::iterator it;
int p[maxn],q[maxn];
struct L{int l,i;};
vector<L>vl[maxn];
inline bool operator <(const L x,const L y){return x.l>y.l;}
priority_queue<L>q1;
struct R{int r,i;};
vector<R>vr[maxn];
inline bool operator <(const R x,const R y){return x.r<y.r;}
priority_queue<R>q2;
bool use[maxn],flag;
int ans[maxn],re;
int solve(const int k,const int ad){ return ans[k]==-1?-1:n-ans[k]+ad; }
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&A[i],&B[i]);
for(int i=0;i<=n;i++) scanf("%d",&C[i]); sort(C,C+n+1);
for(int i=0;i<=n;i++) if(!i||C[i]!=C[i-1]) S.insert((node){C[i],i});
S.insert((node){inf+1,n+1});
for(int i=1;i<=n;i++)
{
it=S.lower_bound((node){A[i],0});
A[i]=(*it).i; p[A[i]]++;
it=S.lower_bound((node){B[i],0});
B[i]=(*it).i;
if(A[i]>B[i])
{
swap(A[i],B[i]); B[i]--;
vl[B[i]].push_back((L){A[i],i});
vr[A[i]].push_back((R){B[i],i});
}
}
for(int i=0;i<=n;i++) p[i]--;
for(int i=1;i<=n+1;i++) p[i]+=p[i-1];
int ad=0;
for(int i=n+1;i>=0;i--)
{
ad+=q[i]; p[i]+=ad; q[i]=0;
for(int j=0;j<vl[i].size();j++) q1.push(vl[i][j]);
if(p[i]<-1&&i!=n+1)
{
while(!q1.empty()&&p[i]<-1)
{
const L now=q1.top(); q1.pop();
if(now.l>i) break;
use[now.i]=true;
p[i]++; ad++; if(now.l) q[now.l-1]--;
if(B[now.i]>i) q[i+1]++,q[B[now.i]+1]--;
re++;
}
if(p[i]<-1) { flag=true; break; }
}
}
if(flag) for(int i=0;i<=n+1;i++) ans[i]=-1;
else
{
ad=0;
for(int i=0;i<=n;i++) ad+=q[i],q[i]=0,p[i]+=ad;
ad=0;
for(int i=0;i<=n;i++)
{
ans[i]=re;
ad+=q[i]; p[i]+=ad;
for(int j=0;j<vr[i].size();j++) if(!use[vr[i][j].i]) q2.push(vr[i][j]);
if(p[i]<0)
{
while(!q2.empty()&&p[i]<0)
{
const R now=q2.top(); q2.pop();
if(now.r<i) break;
ad++; p[i]++; q[now.r+1]--;
re++;
}
if(p[i]<0)
{
for(int j=i+1;j<=n+1;j++) ans[j]=-1;
break;
}
}
}
if(ans[n+1]!=-1) ans[n+1]=re;
}
scanf("%d",&m);
while(m--)
{
int x,y; scanf("%d%d",&x,&y);
it=S.lower_bound((node){x,0}); x=(*it).i;
it=S.lower_bound((node){y,0}); y=(*it).i;
printf("%d\n",max(solve(x,1),solve(y,0)));
}
return 0;
}