bzoj4377: [POI2015]Kurs szybkiego czytania
又被虐爆了QWQ我讲得不清楚的话可以看看这个
读题仔细一点可以发现由于a,n互质所以值会取遍值域,也就是对于每个i(A*i+B)%n的值不等
设这个值为Si,假如我们确定了匹配起点为i,那么就要保证Si+A*0,Si+A*1,……Si+A*(m-1)和p的关系要满足给出的条件,特别的,当i=n-m+1~n-1时由于不足m个元素一定不可行
那么我们可以列出m个不等关系,举个例子,假如当前匹配位置为k,给出的c[k]=0,那么就有0<=Si+A*k<=p-1,注意是模意义下的,所以移项要理解成区间平移,再分情况讨论
最终答案就是这些不等式的解的交集,但是发现某些不等式化简后会变成[0~y]交(交集符号打不出来)[x~n-1]的性质,比较难搞,可以补集转化,变成求不合法的并集,这个排个序扫一遍就好
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int _=1e2; const int maxm=1e6+_; struct node { int l,r; node(){} node(int L,int R){l=L;r=R;} }a[maxm*4];int len; bool cmp(node n1,node n2){return n1.l<n2.l;} int getans()//区间求并 { sort(a+1,a+len+1,cmp); int nowl=a[1].l,nowr=a[1].r,ans=0; for(int i=2;i<=len;i++) { if(a[i].l<=nowr)nowr=max(nowr,a[i].r); else ans+=nowr-nowl+1,nowl=a[i].l,nowr=a[i].r; } ans+=nowr-nowl+1; return ans; } char ss[maxm]; int main() { int n,A,B,p,m; scanf("%d%d%d%d%d",&n,&A,&B,&p,&m); scanf("%s",ss+1); int st=0; for(int i=1;i<=m;i++) { if(ss[i]=='0') { if(st>p-1)// n-st ~ n+p-1-st a[++len]=node(0,n-st-1), a[++len]=node(n+p-1-st+ 1,n-1); else // 0 ~ p-1-st | n-st~n-1 a[++len]=node(p-1-st+1,n-st-1); } else { if(p>=st)// p-st ~ n-1-st a[++len]=node(0,p-st-1), a[++len]=node(n-1-st+1,n-1); else // 0 ~ n-1-st | n+p-st ~ n-1 a[++len]=node(n-1-st+1,n+p-st-1); } st=(st+A)%n; } for(int i=n-m+1;i<n;i++) a[++len]=node((B+LL(A)*i)%n,(B+LL(A)*i)%n); //getseq int tp=0; for(int i=1;i<=len;i++) if(a[i].l<=a[i].r)a[++tp]=a[i]; len=tp; //unique printf("%d\n",n-getans()); return 0; }
pain and happy in the cruel world.