北京集训:20180311

于是今天又是一场愉悦的考试。

笨蒟蒻今天终于不爆零啦!好开心!

T1:


说白了就是要在区间内选出一个子集使之xor和为0。
直觉告诉我这东西线段树。
然而三种标记没法合并啊,怎么办啊......
莫队吧,区间修改不可做。
看80分的值域那么小,要不然,我们来倍增沃尔什变换吧。
不不不,这是什么鬼畜的东西......
算了,40分值域才15,n^2暴力+bitset可过。
好像能线性基?然而40分不需要线性基的,算了不管了暴力了。
然后下来发现大力线性基有80分......
说下正解:
显然当r-l+1>30的时候一定输出Yes(这不显然啊,我怎么没想出来)。
为什么?考虑线性基的插入过程,我们逐个插入,当某个数不能被插入时说明xor出0,符合要求。
而值域10^9代表线性基最多插30个,根据鸽巢原理,当你插入第31个数的时候要么无法插入,要么前面已经插入出0了。
然后我们当r-l+1<=30的时候大力计算即可。
所以我们有了完美的n^2暴力,能过80分。
剩下的20分怎么办呢?考虑用线段树维护修改。
还是老问题,这个标记没法合并。
你可以线段树强行push,显然这样是O(n^2)的,而且是大常数。
其实暴力推倒(不是这个字吧)一下是可以合并的,然而我比较蒻,不愿意推(H是不行的)。
于是我选择按位考虑,or变成数字为1的位强制是1,and变成数字为0位强制是0,xor变成区间01互换。
好的,我们可以每个节点开31个char去维护这个东西是吧......
然后就有了一个常数巨大的伪正解。
考场40分代码:

 1 #include<bits/stdc++.h>
 2 #define debug cout
 3 using namespace std;
 4 const int maxn=1e3+1e2,maxe=64,maxl=32;
 5 typedef bitset<maxe> BitSet;
 6 
 7 int in[maxn],n;
 8 BitSet prv[maxn];
 9 
10 inline BitSet trans(const BitSet &sou,const int &x) {
11     BitSet ret = sou;
12     for(int i=0;i<maxl;i++) if( sou[i] ) ret[i^x] = 1;
13     return ret;
14 }
15 
16 inline void getprv(int l,int r) {
17     prv[l] &= 0; prv[l][in[l]] = 1;
18     for(int i=l+1;i<=r;i++) prv[i] = trans(prv[i-1],in[i]) , prv[i][in[i]] = 1;
19 }
20 inline bool getans(int l,int r) {
21     if( !in[l] ) return 1;
22     for(int i=l+1;i<=r;i++) if( !in[i] || prv[i-1][in[i]] ) return 1;
23     return 0;
24 }
25 
26 inline void modify(int l,int r,int x,int o) {
27     if( o == 1 ) for(int i=l;i<=r;i++) in[i] &= x;
28     if( o == 2 ) for(int i=l;i<=r;i++) in[i] |= x;
29     if( o == 3 ) for(int i=l;i<=r;i++) in[i] ^= x;
30 }
31 
32 int main() {
33     static int q;
34     scanf("%d",&n);
35     for(int i=1;i<=n;i++) scanf("%d",in+i);
36     scanf("%d",&q);
37     for(int i=1,o,l,r,x;i<=q;i++) {
38         scanf("%d%d%d",&o,&l,&r);
39         if( !o ) {
40             getprv(l,r);
41             puts(getans(l,r)?"Yes":"No");
42         } else {
43             scanf("%d",&x);
44             modify(l,r,x,o);
45         }
46     }
47     return 0;
48 }
View Code

暴力线段树80分代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cctype>
  5 #define debug cerr
  6 using namespace std;
  7 const int maxn=1e5+1e2,maxl=32;
  8 
  9 int in[maxn],n;
 10 struct SegmentTree {
 11     int l[maxn<<2],r[maxn<<2],lson[maxn<<2],rson[maxn<<2],cnt;
 12     int lazy[maxn<<2][3]; // 0 xor , 1 and , 2 or .
 13     
 14     inline void getpe(int tpe,int &reta,int &retb) {
 15         if( tpe == 0 ) reta = 1 , retb = 2;
 16         else if( tpe == 1 ) reta = 0 , retb = 2;
 17         else if( tpe == 2 ) reta = 0 , retb = 1;
 18     }
 19     inline void apply(int pos,int val,int tpe) {
 20         if( l[pos] == r[pos] ) {
 21             if( tpe == 0 ) in[l[pos]] ^= val;
 22             if( tpe == 1 ) in[l[pos]] &= val;
 23             if( tpe == 2 ) in[l[pos]] |= val;
 24         }
 25         int ta,tb; getpe(tpe,ta,tb);
 26         if( ~lazy[pos][ta] || ~lazy[pos][tb] ) push(pos);
 27         if( !~lazy[pos][tpe] ) lazy[pos][tpe] = val;
 28         else {
 29             if( tpe == 0 ) lazy[pos][tpe] ^= val;
 30             if( tpe == 1 ) lazy[pos][tpe] &= val;
 31             if( tpe == 2 ) lazy[pos][tpe] |= val;
 32         }
 33     }
 34     inline void push(int pos) {
 35         if( l[pos] == r[pos] ) return;
 36         for(int i=0;i<3;i++)
 37             if( ~lazy[pos][i] ) {
 38                 apply(lson[pos],lazy[pos][i],i) ,
 39                 apply(rson[pos],lazy[pos][i],i) ;
 40                 lazy[pos][i] = -1;
 41             }
 42     }
 43     inline void build(int pos,int ll,int rr) {
 44         l[pos] = ll , r[pos] = rr;
 45         if( ll == rr ) return;
 46         const int mid = ( ll + rr ) >> 1;
 47         build(lson[pos]=++cnt,ll,mid) ,
 48         build(rson[pos]=++cnt,mid+1,rr) ;
 49     }
 50     inline void update(int pos,int ll,int rr,int val,int tpe) {
 51         if( ll <= l[pos] && r[pos] <= rr ) return apply(pos,val,tpe);
 52         const int mid = ( l[pos] + r[pos] ) >> 1;
 53         push(pos);
 54         if( rr <= mid ) return update(lson[pos],ll,rr,val,tpe);
 55         if( ll > mid ) return update(rson[pos],ll,rr,val,tpe);
 56         update(lson[pos],ll,rr,val,tpe) , update(rson[pos],ll,rr,val,tpe);
 57     }
 58     inline int query(int pos,int tar) {
 59         if( l[pos] == r[pos] ) return in[l[pos]];
 60         const int mid = ( l[pos] + r[pos] ) >> 1;
 61         push(pos);
 62         if( tar <= mid ) return query(lson[pos],tar);
 63         else return query(rson[pos],tar);
 64     }
 65     SegmentTree() {
 66         memset(lazy,-1,sizeof(lazy));
 67     }
 68 }segt;
 69 
 70 struct LinerBase {
 71     int dat[maxl];
 72     inline bool insert(int x) {
 73         for(int i=31;~i;i--)
 74             if( x & ( 1 << i ) ) {
 75                 if( dat[i] ) x ^= dat[i];
 76                 else {
 77                     dat[i] = x;
 78                     return 1;
 79                 }
 80             }
 81         return 0;
 82     }
 83     inline void reset() {
 84         memset(dat,0,sizeof(dat));
 85     }
 86 }lb;
 87 
 88 inline bool query(int l,int r) {
 89     if( r - l + 1 > 30 ) return 1;
 90     lb.reset();
 91     for(int i=l,q;i<=r;i++) {
 92         q = segt.query(1,i);
 93         if( !lb.insert(q) ) return 1;
 94     }
 95     return 0;
 96 }
 97 
 98 __inline char nxtchar() {
 99     return getchar();
100     static const int BS = 1 << 21;
101     static char buf[BS],*st=buf+BS,*ed=buf+BS;
102     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
103     return st == ed ? -1 : *st++;
104 }
105 __inline int getint() {
106     int ret = 0 , ch;
107     while( !isdigit(ch=nxtchar()) );
108     do ret=ret*10+ch-'0'; while( isdigit(ch=nxtchar()) );
109     return ret;
110 }
111 
112 
113 int main() {
114     static int m;
115     n = getint();
116     for(int i=1;i<=n;i++) in[i] = getint();
117     segt.build(segt.cnt=1,1,n);
118     m = getint();
119     for(int i=1,o,l,r,x;i<=m;i++) {
120         o = getint() , l = getint() , r = getint();
121         if( !o ) puts(query(l,r)?"Yes":"No");
122         else {
123             x = getint() , o %= 3;
124             segt.update(1,l,r,x,o);
125         }
126     }
127     return 0;
128 }
View Code

正解代码:

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cctype>
  5 const int maxn=1e5+1e2,maxl=32;
  6 
  7 unsigned in[maxn];
  8 int n;
  9 struct SegmentTree {
 10     int l[maxn<<2],r[maxn<<2],lson[maxn<<2],rson[maxn<<2],cnt;
 11     struct Node {
 12         char dat[maxl];
 13         char& operator [] (const int &x) {
 14             return dat[x];
 15         }
 16         inline bool empty() {
 17             for(int i=0;i<maxl;i++) if( ~dat[i] ) return 0;
 18             return 1;
 19         }
 20         inline void reset() {
 21             memset(dat,-1,sizeof(dat));
 22         }
 23         inline unsigned build() {
 24             unsigned ret = 0;
 25             for(int i=0;i<maxl;i++) {
 26                 //if( !~dat[i] ) throw "You shouldn't build this ."; ???
 27                 ret |= ( (unsigned) dat[i] << i );
 28             }
 29             return ret;
 30         }
 31         inline void fill(unsigned x) {
 32             for(int i=0;i<maxl;i++) dat[i] = ( x >> i ) & 1;
 33         }
 34         Node() {
 35             memset(dat,-1,sizeof(dat));
 36         }
 37     }ns[maxn<<2],lazy[maxn<<2]; // lazy = 1 means fill 1 , lazy = 0 means fill 0 , lazy = 2 means neg , lazy = -1 means nothing to do .
 38     inline void apply(int pos,Node &sou) {
 39         for(int i=0;i<maxl;i++) if( ~sou[i] ) {
 40             if( sou[i] != 2 ) ns[pos][i] = lazy[pos][i] = sou[i];
 41             else {
 42                 ns[pos][i] ^= 1;
 43                 if( !~lazy[pos][i] ) lazy[pos][i] = 2;
 44                 else if( lazy[pos][i] == 2 ) lazy[pos][i] = -1;
 45                 else lazy[pos][i] ^= 1;
 46             }
 47         }
 48     }
 49     inline void push(int pos) {
 50         if( l[pos] == r[pos] || lazy[pos].empty() ) return;
 51         apply(lson[pos],lazy[pos]) ,
 52         apply(rson[pos],lazy[pos]) ;
 53         lazy[pos].reset();
 54     }
 55     inline void build(int pos,int ll,int rr) {
 56         l[pos] = ll , r[pos] = rr;
 57         if( ll == rr ) return ns[pos].fill(in[ll]);
 58         const int mid = ( ll + rr ) >> 1;
 59         build(lson[pos]=++cnt,ll,mid) ,
 60         build(rson[pos]=++cnt,mid+1,rr) ;
 61     }
 62     inline void update(int pos,int ll,int rr,Node &o) {
 63         if( ll <= l[pos] && r[pos] <= rr ) return apply(pos,o);
 64         const int mid = ( l[pos] + r[pos] ) >> 1;
 65         push(pos);
 66         if( rr <= mid ) return update(lson[pos],ll,rr,o);
 67         if( ll > mid ) return update(rson[pos],ll,rr,o);
 68         update(lson[pos],ll,rr,o) , update(rson[pos],ll,rr,o);
 69     }
 70     inline unsigned query(int pos,int tar) {
 71         if( l[pos] == r[pos] ) return ns[pos].build();
 72         const int mid = ( l[pos] + r[pos] ) >> 1;
 73         push(pos);
 74         if( tar <= mid ) return query(lson[pos],tar);
 75         else return query(rson[pos],tar);
 76     }
 77     SegmentTree() {
 78         memset(lazy,-1,sizeof(lazy));
 79     }
 80 }segt;
 81 
 82 struct LinerBase {
 83     unsigned dat[maxl];
 84     inline bool insert(unsigned x) {
 85         for(int i=31;~i;i--)
 86             if( x & ( 1 << i ) ) {
 87                 if( dat[i] ) x ^= dat[i];
 88                 else {
 89                     dat[i] = x;
 90                     return 1;
 91                 }
 92             }
 93         return 0;
 94     }
 95     inline void reset() {
 96         memset(dat,0,sizeof(dat));
 97     }
 98 }lb;
 99 
100 inline bool query(int l,int r) {
101     if( r - l + 1 > 30 ) return 1;
102     lb.reset();
103     for(int i=l,q;i<=r;i++) {
104         q = segt.query(1,i);
105         if( !lb.insert(q) ) return 1;
106     }
107     return 0;
108 }
109 
110 inline SegmentTree::Node getnode(const unsigned &x,const int o) {
111     SegmentTree::Node ret;
112     if( !o ) {
113         for(int i=0;i<maxl;i++) if( ( x >> i ) & 1 ) ret[i] = 2;
114     } else if( o == 1 ) {
115         for(int i=0;i<maxl;i++) if( ! ( ( x >> i ) & 1 ) ) ret[i] = 0;
116     } else if( o == 2 ) {
117         for(int i=0;i<maxl;i++) if( ( x >> i ) & 1u ) ret[i] = 1;
118     }
119     return ret;
120 }
121 
122 inline char nxtchar() {
123     static const int BS = 1 << 21;
124     static char buf[BS],*st=buf+BS,*ed=buf+BS;
125     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
126     return st == ed ? -1 : *st++;
127 }
128 inline int getint() {
129     int ret = 0 , ch;
130     while( !isdigit(ch=nxtchar()) );
131     do ret=ret*10+ch-'0'; while( isdigit(ch=nxtchar()) );
132     return ret;
133 }
134 
135 
136 int main() {
137     static int m;
138     static unsigned x;
139     static SegmentTree::Node ONode;
140     n = getint();
141     for(int i=1;i<=n;i++) in[i] = getint();
142     segt.build(segt.cnt=1,1,n);
143     m = getint();
144     for(int i=1,o,l,r;i<=m;i++) {
145         o = getint() , l = getint() , r = getint();
146         if( !o ) puts(query(l,r)?"Yes":"No");
147         else {
148             x = getint() , o %= 3;
149             ONode = getnode(x,o);
150             segt.update(1,l,r,ONode);
151         }
152     }
153     return 0;
154 }
View Code

 

T2:


首先不要被这题面吓到......
他说出现位置完全相同,好像似曾相识的样子啊,等等,这不就是后缀自动机的节点的right集合的性质吗?
所以第一个条件就是说我们不能在根节点到其他点的一条链上选出两个人。
第二个条件就是我们需要找一些链覆盖所有节点。
好的,建立广义SAM然后跑最小链覆盖不就好了。
无解什么鬼啊?怕不是炸胡,样例没有我也构造不出来,不管他了QAQ。
于是这样你就get到了30分......
为什么?显然一个人认识的人并不是在一般的一条链上,而是在从根节点到这个点的一条链。
也就是说,我们最小链覆盖的所有链都必须从根节点的后继节点开始。
这东西最小链覆盖没法做了,我们需要拆点然后跑有上下界的最小流。
最小流怎么办?首先先随便找出一条可行流,拆掉超级源超级汇和inf边,再由汇点向源点退流,减去退掉的流量就好了。
考场30分代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<map>
  6 #include<queue>
  7 #define debug cout
  8 using namespace std;
  9 const int maxn=5e3+1e2;
 10 const int inf=0x3f3f3f3f;
 11 
 12 int in[maxn],n,ans;
 13 
 14 namespace NetworkFlow {
 15     int s[maxn<<2],t[maxn<<6],nxt[maxn<<6],f[maxn<<6],dep[maxn<<2];
 16     int st,ed;
 17     inline void coredge(int from,int to,int flow) {
 18         static int cnt = 1;
 19         t[++cnt] = to , f[cnt] = flow ,
 20         nxt[cnt] = s[from] , s[from] = cnt;
 21     }
 22     inline void singledge(int from,int to,int flow) {
 23         coredge(from,to,flow) , coredge(to,from,0);
 24     }
 25     inline bool bfs() {
 26         memset(dep,-1,sizeof(dep)) , dep[st] = 0;
 27         queue<int> q; q.push(st);
 28         while( q.size() ) {
 29             const int pos = q.front(); q.pop();
 30             for(int at=s[pos];at;at=nxt[at])
 31                 if( f[at] && !~dep[t[at]] )
 32                     dep[t[at]] = dep[pos] + 1 , q.push(t[at]);
 33         }
 34         return ~dep[ed];
 35     }
 36     inline int dfs(int pos,int flow) {
 37         if( pos == ed ) return flow;
 38         int ret = 0 , now = 0;
 39         for(int at=s[pos];at;at=nxt[at])
 40             if( f[at] && dep[t[at]] > dep[pos] ) {
 41                 now = dfs(t[at],min(flow,f[at])) ,
 42                 ret += now , flow -= now ,
 43                 f[at] -= now , f[at^1] += now;
 44                 if( !flow ) return ret;
 45             }
 46         if( !ret ) dep[pos] = -1;
 47         return ret;
 48     }
 49     inline int dinic() {
 50         int ret = 0 , now = 0;
 51         while( bfs() ) {
 52             while( ( now = dfs(st,inf) ) )
 53                 ret += now;
 54         }
 55         return ret;
 56     }
 57 }
 58 
 59 namespace SAM {
 60     map<int,int> ch[maxn<<1];
 61     int fa[maxn<<1],len[maxn<<1],root,last,cnt;
 62     
 63     inline int NewNode(int ll) {
 64         len[++cnt] = ll;
 65         return cnt;
 66     }
 67     inline void extend(int x) {
 68         int p = last;
 69         int np = NewNode(len[p]+1);
 70         while( p && ch[p].find(x) == ch[p].end() ) ch[p][x] = np , p = fa[p];
 71         if( !p ) fa[np] = root;
 72         else {
 73             int q = ch[p][x];
 74             if( len[q] == len[p] + 1 ) fa[np] = q;
 75             else {
 76                 int nq = NewNode(len[p]+1);
 77                 ch[nq] = ch[q] , fa[nq] = fa[q];
 78                 fa[np] = fa[q] = nq;
 79                 while( p && ch[p][x] == q ) ch[p][x] = nq , p = fa[p];
 80             }
 81         }
 82         last = np;
 83     }
 84     inline void Ex_extend(int* sou,int li) {
 85         last = root;
 86         for(int i=1;i<=li;i++) {
 87             if( ch[last].find(sou[i]) != ch[last].end() ) last = ch[last][sou[i]];
 88             else extend(sou[i]);
 89         }
 90     }
 91 }
 92 
 93 inline void build() {
 94     using SAM::ch;using SAM::cnt;
 95     using NetworkFlow::singledge; using NetworkFlow::st; using NetworkFlow::ed;
 96     st = cnt * 2 + 1 , ed = st + 1;
 97     #define cov(x) (x+cnt)
 98     for(int i=1;i<=cnt;i++) {
 99         singledge(st,i,1) , singledge(cov(i),ed,1);
100         for(map<int,int>::iterator it=ch[i].begin();it!=ch[i].end();++it)
101             singledge(i,cov(it->second),1);
102     }
103     ans = cnt;
104 }
105 
106 int main() {
107     static int k,m;
108     SAM::root = SAM::NewNode(0);
109     scanf("%d%d",&k,&m);
110     if( k == 1 ) return puts("1"),0;
111     while(m--) {
112         scanf("%d",&n);
113         for(int i=1;i<=n;i++) scanf("%d",in+i);
114         SAM::Ex_extend(in,n);
115     }
116     build();
117     ans -= NetworkFlow::dinic();
118     printf("%d\n",ans);
119     return 0;
120 }
View Code

正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<map>
  6 #include<queue>
  7 #define debug cout
  8 using namespace std;
  9 const int maxn=5e3+1e2;
 10 const int inf=0x3f3f3f3f;
 11  
 12 int in[maxn],n,ans,sum;
 13  
 14 namespace NetworkFlow {
 15     int s[maxn<<2],t[maxn<<6],nxt[maxn<<6],f[maxn<<6],dep[maxn<<2],deg[maxn<<2],cnt=1;
 16     int bak[maxn<<2],bcnt;
 17     int st,ed,_s,_t;
 18     inline void coredge(int from,int to,int flow) {
 19         t[++cnt] = to , f[cnt] = flow ,
 20         nxt[cnt] = s[from] , s[from] = cnt;
 21     }
 22     inline void singledge(int from,int to,int flow) {
 23         coredge(from,to,flow) , coredge(to,from,0);
 24     }
 25     inline bool bfs() {
 26         memset(dep,-1,sizeof(dep)) , dep[st] = 0;
 27         queue<int> q; q.push(st);
 28         while( q.size() ) {
 29             const int pos = q.front(); q.pop();
 30             for(int at=s[pos];at;at=nxt[at])
 31                 if( f[at] && !~dep[t[at]] ) {
 32                     dep[t[at]] = dep[pos] + 1 , q.push(t[at]);
 33                 }
 34         }
 35         return ~dep[ed];
 36     }
 37     inline int dfs(int pos,int flow) {
 38         if( pos == ed ) return flow;
 39         int ret = 0 , now = 0;
 40         for(int at=s[pos];at;at=nxt[at])
 41             if( f[at] && dep[t[at]] > dep[pos] ) {
 42                 now = dfs(t[at],min(flow,f[at])) ,
 43                 ret += now , flow -= now ,
 44                 f[at] -= now , f[at^1] += now;
 45                 if( !flow ) return ret;
 46             }
 47         if( !ret ) dep[pos] = -1;
 48         return ret;
 49     }
 50     inline int dinic() {
 51         int ret = 0 , now = 0;
 52         while( bfs() ) {
 53             while( ( now = dfs(st,inf) ) )
 54                 ret += now;
 55         }
 56         return ret;
 57     }
 58     inline int findflow() {
 59         for(int at=s[_t];at;at=nxt[at])
 60             if( t[at] = _s ) return f[at^1];
 61         throw "It shouldn't be here";
 62     }
 63     inline void backup() {
 64         memcpy(bak,s,sizeof(s)) , bcnt = cnt;
 65     }
 66     inline void restore() {
 67         memcpy(s,bak,sizeof(bak)) , cnt = bcnt;
 68     }
 69 }
 70  
 71 namespace SAM {
 72     map<int,int> ch[maxn<<1];
 73     int fa[maxn<<1],len[maxn<<1],root,last,cnt;
 74      
 75     inline int NewNode(int ll) {
 76         len[++cnt] = ll;
 77         return cnt;
 78     }
 79     inline void extend(int x) {
 80         int p = last;
 81         int np = NewNode(len[p]+1);
 82         while( p && ch[p].find(x) == ch[p].end() ) ch[p][x] = np , p = fa[p];
 83         if( !p ) fa[np] = root;
 84         else {
 85             int q = ch[p][x];
 86             if( len[q] == len[p] + 1 ) fa[np] = q;
 87             else {
 88                 int nq = NewNode(len[p]+1);
 89                 ch[nq] = ch[q] , fa[nq] = fa[q];
 90                 fa[np] = fa[q] = nq;
 91                 while( p && ch[p][x] == q ) ch[p][x] = nq , p = fa[p];
 92             }
 93         }
 94         last = np;
 95     }
 96     inline void Ex_extend(int* sou,int li) {
 97         last = root;
 98         for(int i=1;i<=li;i++) {
 99             if( ch[last].find(sou[i]) != ch[last].end() ) last = ch[last][sou[i]];
100             else extend(sou[i]);
101         }
102     }
103 }
104  
105 inline void build() {
106     using SAM::ch;using SAM::cnt;
107     using namespace NetworkFlow;
108     _s = cnt * 2 + 1 , _t = _s + 1 , st = _t + 1 , ed = st + 1;
109     #define cov(x) (x+cnt)
110     for(int i=1;i<=cnt;i++) {
111         if( i != 1 ) ++deg[i] , --deg[cov(i)];
112         for(map<int,int>::iterator it=ch[i].begin();it!=ch[i].end();it++) {
113             const int tar = it->second;
114             if( i == 1 ) singledge(_s,tar,1);
115             else singledge(cov(i),tar,1);
116         }
117         if( i != 1 ) singledge(cov(i),_t,1);
118     }
119     backup();
120     for(int i=1;i<=_t;i++) {
121         if( !deg[i] ) continue;
122         if( deg[i] > 0 ) singledge(i,ed,deg[i]) , sum += deg[i];
123         else singledge(st,i,-deg[i]);
124     }
125     singledge(_t,_s,inf);
126 }
127 inline int getans() {
128     using namespace NetworkFlow;
129     int d = dinic();
130     if( d != sum ) return 0; // No solution .
131     int ret = findflow();
132     restore();
133     st = _t , ed = _s;
134     int dd = dinic();
135     return ret - dd;
136 }
137 
138 int main() {
139     static int k,m;
140     SAM::root = SAM::NewNode(0);
141     scanf("%d%d",&k,&m);
142     if( k == 1 ) return puts("1"),0;
143     while(m--) {
144         scanf("%d",&n);
145         for(int i=1;i<=n;i++) scanf("%d",in+i);
146         SAM::Ex_extend(in,n);
147     }
148     build();
149     ans = getans();
150     printf("%d\n",ans);
151     return 0;
152 }
View Code

 

T3:


人生第一道交互题啊......
一看又是神仙题,好的,既然算出一个多项式有40%的分,那我钦定m为0,扔掉b,让他帮我插值,我直接NTT求解A好了。
什么?他没告诉我原根?好吧,我自己求。
求原根这种东西,反正就是把p-1先分解质因数,然后保证x^(p/div[i])在mod p意义下不为1就行了。
原根不能很大,暴力一个一个找就可以通过的说。
(一下为吐槽时间)
然后写了,调了,WA样例了......检查NTT,没错......输出插值用的x,没错......
自行插值他给的多项式,等等,怎么我计算出的值和他算出的不一样啊?
怕不是交互库WA了,去看通知,10:54有一个修正......
赶紧下载下来看看,woc怎么还是WA的?
改用单点插值看看,好,对了。
交互库WA了什么的,这是天不让我做题啊。
好的,单点插值交吧,反正大家都没法做就是了。
11:04,再次修正,这次交互库终于对了......
(吐槽时间结束)
官方题解放上来吧,真·神仙打架(蒟蒻只能瑟瑟发抖):


考场31分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include"poly.h"
 6 //#define fixed
 7 typedef long long int lli;
 8 using namespace std;
 9 const int maxn=65539;
10 
11 int mod,g,len,n;
12 lli ans[maxn],tp[maxn];
13 int oty[maxn];
14 
15 inline lli fastpow(lli base,int tim) {
16     lli ret = 1;
17     while( tim ) {
18         if( tim & 1 ) ret = ret * base % mod;
19         if( tim >>= 1 ) base = base * base % mod;
20     }
21     return ret % mod;
22 }
23 inline void NTT(lli* dst,int n,int ope) {
24     for(int i=0,j=0;i<n;i++) {
25         if( i < j ) swap( dst[i] , dst[j] );
26         for(int t=n>>1;(j^=t)<t;t>>=1) ;
27     }
28     for(int len=2;len<=n;len<<=1) {
29         const int h = len >> 1;
30         lli per = fastpow(g,mod/(len));
31         if( !~ope ) per = fastpow(per,mod-2);
32         for(int st=0;st<n;st+=len) {
33             lli w = 1;
34             for(int pos=0;pos<h;pos++) {
35                 const lli u = dst[st+pos] , v = dst[st+pos+h] * w % mod;
36                 dst[st+pos] = ( u + v ) % mod ,
37                 dst[st+pos+h] = ( u - v + mod ) % mod ,
38                 w = w * per % mod;
39             }
40         }
41     }
42     if( !~ope ) {
43         const lli mul = fastpow(n,mod-2);
44         for(int i=0;i<n;i++) dst[i] = dst[i] * mul % mod;
45     }
46 }
47 
48 namespace FindRoot {
49     int divs[maxn],cnt;
50     inline void cut(int x) {
51         for(int i=2;(lli)i*i<=x;i++)
52             if( ! ( x % i ) ) {
53                 divs[++cnt] = i;
54                 while( ! ( x % i ) ) x /= i;
55             }
56     }
57     inline bool judge(int x) {
58         for(int i=1;i<=cnt;i++)
59             if( fastpow(x,mod/divs[i]) == 1 ) return 0;
60         return 1;
61     }
62     inline int findrt() {
63         cut(mod-1);
64         for(int i=2;i<mod;i++) if( judge(i) ) return i;
65         throw "There is no primary root ! ";
66     }
67 }
68 
69 int init(int l,int r,int _n,int P) {
70     ++_n;
71     for(len=1;len<=_n;len<<=1) ;
72     mod = P , n = _n , g = FindRoot::findrt();
73     return 0;
74 }
75 void solve(int *A,int *B) {
76     for(int i=0;i<len;i++) tp[i] = fastpow(g,(mod/len)*i);
77     //#ifdef fixed
78         for(int i=len;i;i--) tp[i] = tp[i-1];
79         get(len,tp,oty);
80         for(int i=0;i<len;i++) ans[i] = oty[i+1];
81     /*#else
82         for(int i=0;i<len;i++) ans[i] = get(tp[i]);
83     #endif*/
84     NTT(ans,len,-1);
85     for(int i=0;i<n;i++) A[i] = B[i] = ans[i];
86 }
View Code

某不科学的超(时)std(卡评测8分钟的说):

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define rep(i,a,b) for (int i = a, _ = b; i <= _; i ++)
  4 #define per(i,a,b) for (int i = a, _ = b; i >= _; i --)
  5 #define For(i,a,b) for (int i = a, _ = b; i <  _; i ++)
  6  
  7 #include <ext/pb_ds/assoc_container.hpp>
  8 #include <ext/pb_ds/hash_policy.hpp>
  9  
 10 #include "poly.h"
 11  
 12 typedef long long ll;
 13  
 14 int mod, g;
 15  
 16 namespace Interpolation {
 17  
 18 #define iter(i, n) for (int i = 1; i <= n; ++i)
 19 #define iter0(i, n) for (int i = 0; i < n; ++i)
 20 #define forw(i, a, b) for (int i = a; i <= b; ++i)
 21 #define down(i, a, b) for (int i = b; i >= a; --i)
 22  
 23 #define reset(a, l, r) forw(i, l, r) a[i] = 0;
 24 #define NR 401000
 25  
 26   typedef vector<int> Poly;
 27  
 28   inline int pr(int a, int z) {
 29     int s = 1;
 30     while (z > 0) {
 31       if (z % 2 == 1) s = 1ll * s * a % mod;
 32       a = 1ll * a * a % mod;
 33       z /= 2;
 34     }
 35     return s;
 36   }
 37  
 38   inline int mod_inv(int a) { return pr(a, mod - 2); }
 39  
 40   void fft(int *a, int n, int ty) {
 41     for (int i = n >> 1, j = 1, k; j < n - 1; ++j) {
 42       if (i > j) swap(a[i], a[j]);
 43       for (k = n >> 1; k <= i; k >>= 1) i ^= k;
 44       i ^= k;
 45     }
 46  
 47     for (int m = 2; m <= n; m <<= 1) {
 48       int h = m >> 1, wm = pr(g, (mod - 1) / m * (ty == +1 ? 1 : (m - 1)));
 49  
 50       for (register int i = 0; i < n; i += m) {
 51     register int w = 1;
 52     for (int j = i; j < i + h; ++j) {
 53       register int u = a[j], v = 1ll * w * a[j + h] % mod;
 54                      
 55       a[j] = (u + v) % mod;
 56       a[j + h] = (u - v + mod) % mod;
 57       w = 1ll * w * wm % mod;
 58     }
 59       }
 60     }
 61  
 62     if (ty == -1) {
 63       int iv = mod_inv(n);
 64       iter0(i, n) a[i] = 1ll * a[i] * iv % mod;
 65     }
 66   }
 67  
 68   ostream& operator<<(ostream &output, const Poly &a){  
 69     output << "[";
 70     int la = a.size();
 71     iter0(i, la)
 72       output << a[i] << (i + 1 == la ? ']' : ',');
 73     return output;
 74   }
 75  
 76   void upd(Poly &a) { while (!a.empty() && a.back() == 0) a.pop_back(); }
 77  
 78   inline Poly operator+(const Poly &a, const Poly &b) {
 79     int la = a.size(), lb = b.size();
 80     int lc = max(la, lb);
 81     Poly c(lc);
 82     iter0(i, lc) c[i] = ((i < la ? a[i] : 0) + (i < lb ? b[i] : 0)) % mod;
 83     return upd(c), c;
 84   }
 85   inline void poly_multo(int a[], int b[], int N) {
 86     fft(a, N, +1), fft(b, N, +1);
 87     iter0(i, N) a[i] = 1ll * a[i] * b[i] % mod;
 88     fft(a, N, -1);
 89   }
 90  
 91   int ta[NR], tb[NR];
 92  
 93   Poly operator*(const Poly &a, const Poly &b) {
 94     int la = a.size(), lb = b.size();
 95          
 96     Poly c(la + lb - 1);
 97          
 98     if (la + lb <= 100) {
 99       iter0(i, la) iter0(j, lb) c[i + j] = (c[i + j] + 1ll * a[i] * b[j]) % mod;
100     } else {
101       int N;
102       for (N = 1; N < la + lb; N <<= 1);
103       iter0(i, N) {
104     ta[i] = (i < la ? a[i] : 0);
105     tb[i] = (i < lb ? b[i] : 0);
106       }
107       poly_multo(ta, tb, N);
108       iter0(i, la + lb - 1) c[i] = ta[i];
109     }
110     return upd(c), c;
111   }
112   int ccc = 0;
113   int ti[NR];
114  
115   void poly_inv(int *f, int *inv, int n) {
116     if (n == 0) {
117       inv[0] = mod_inv(f[0]);
118       return;
119     }
120     poly_inv(f, inv, n / 2);
121     static int t[140000];
122     int N = 1;
123     for (; N <= n * 2; N <<= 1);
124     iter0(i, N) t[i] = i <= n ? f[i] : 0; reset(inv, n / 2 + 1, N);
125     fft(inv, N, +1); fft(t, N, +1);
126     iter0(i, N) inv[i] = (2 + mod - 1ll * inv[i] * t[i] % mod) * inv[i] % mod;
127     fft(inv, N, -1);
128   }
129  
130   void poly_mod(int *a, int *b, int *c, int n, int m) {
131     if (n < m) {
132       iter0(i, m) c[i] = i <= n ? a[i] : 0;
133       return;
134     }
135     static int f[140000], g[140000];
136     if (n < 100) {
137       int invb = mod_inv(b[m]);
138       memcpy(f, a, sizeof(int) * (n + 1));
139       down(i, n, m) {
140     int t = 1ll * f[i] * invb % mod;
141     forw(j, 0, m) (f[i - j] += mod - 1ll * t * b[m - j] % mod) %= mod;
142       }
143       memcpy(c, f, sizeof(int) * m);
144       return;
145     }
146          
147     int N;
148     for (N = 1; N <= max(n, 2 * (n - m)) + 10; N <<= 1);
149     reset(g, 0, N);
150          
151     forw(i, 0, n - m) f[i] = i <= m ? b[m - i] : 0; reset(f, n - m + 1, N);
152     poly_inv(f, g, n - m); reset(g, n - m + 1, N);
153     forw(i, 0, n - m) f[i] = a[n - i];
154     poly_multo(g, f, N);
155     reset(g, n - m + 1, N);
156     reverse(g, g + n - m + 1);
157     forw(i, 0, m) f[i] = b[i]; reset(f, m + 1, N);
158     poly_multo(f, g, N);
159     iter0(i, m) c[i] = (a[i] + mod - f[i]) % mod;
160   }
161   int tr[NR];
162  
163   Poly operator%(const Poly &a, const Poly &b) {
164          
165     int la = a.size(), lb = b.size(), N;
166     Poly c(lb);
167     for (N = 1; N < la + lb; N <<= 1);
168     iter0(i, N) {
169       ta[i] = (i < la ? a[i] : 0);
170       tb[i] = (i < lb ? b[i] : 0);
171     }
172     poly_mod(ta, tb, tr, la - 1, lb - 1);
173          
174     iter0(i, lb) c[i] = tr[i];
175     iter0(i, N) tr[i] = 0;
176     upd(c);
177          
178     return c;
179   }
180   Poly t[NR], tt[NR];
181   int tsz, lc[NR], rc[NR];
182  
183  
184   void init(int &x, int l, int r, int *a) {
185     x = ++tsz;
186     if (l == r) {
187       t[x] = { (mod - a[l]) % mod, 1 };
188       return;
189     }
190     int mid = (l + r) / 2;
191     init(lc[x], l, mid, a);
192     init(rc[x], mid + 1, r, a);
193     t[x] = t[lc[x]] * t[rc[x]];
194   }
195  
196   int eval(const Poly &A, int x) {
197     int p = 1, res = 0;
198     for (auto it = A.begin(); it != A.end(); ++it) {
199       res = (res + 1ll * p * *it) % mod;
200       p = 1ll * p * x % mod;
201     }
202     return res;
203   }
204  
205   int pp[NR];
206  
207   Poly D(const Poly &a) {
208     int la = a.size();
209     Poly c(la - 1);
210     iter(i, la - 1) c[i - 1] = 1ll * i * a[i] % mod;
211     return c;
212   }
213  
214   void s2(int x, int l, int r, const Poly &f, int qX[], int ans[]) {
215     if (f.size() < 1000 || r - l + 1 <= 200) {
216       forw(i, l, r) pp[i] = 1;
217       for (auto it = f.begin(); it != f.end(); ++it) {
218     forw(i, l, r) {
219       ans[i] = (ans[i] + 1ll * pp[i] * *it) % mod;
220       pp[i] = 1ll * pp[i] * qX[i] % mod;
221     }
222       }
223       return;
224     }
225  
226     int mid = (l + r) / 2;
227     s2(lc[x], l, mid, f % t[lc[x]], qX, ans);
228     s2(rc[x], mid + 1, r, f % t[rc[x]], qX, ans);
229   }
230   int root;
231  
232  
233  
234   void evaluation(const Poly &f, bool inited, int qX[], int ans[], int m) {
235     if (!inited) {
236       tsz = 0;
237       init(root, 1, m, qX);
238     }
239     s2(root, 1, m, f, qX, ans);
240          
241   }
242  
243   int px[NR], py[NR], qx[NR], qy[NR], Q[NR], n, m;
244  
245   Poly s1(int x, int l, int r) {
246     if (l == r) {
247       Poly tmp = { (int) (1ll * py[l] * mod_inv(Q[l]) % mod) };
248       return tmp;
249     }
250     int mid = (l + r) / 2;
251     Poly L = s1(lc[x], l, mid), R = s1(rc[x], mid + 1, r);
252     return L * t[rc[x]] + R * t[lc[x]];
253   }
254  
255   Poly interpolation(int m, long long *x, int *y) {
256     n = m;
257     for (int i = 1; i <= n; i ++)
258       px[i] = x[i] % mod, py[i] = y[i];
259     init(root, 1, n, px);
260     evaluation(D(t[1]), true, px, Q, n);
261     return s1(root, 1, n);
262   }
263  
264 }
265  
266 inline int rnd() {
267   if (RAND_MAX < mod)
268     return rand() << 15 | rand();
269   else
270     return rand();
271 }
272  
273 inline int Pow(ll a, ll b, int p = mod) {
274   int t = 1;
275   //b %= p - 1;
276   a %= p;
277   while (b) {
278     if (b & 1) t = 1ll * t * a % p;
279     a = 1ll * a * a % p, b >>= 1;
280   }
281   return t;
282 }
283    
284 inline bool check(int x, int k) {
285   return (mod - 1) % k == 0 && k != mod - 1 && Pow(x, k) == 1;
286 }
287  
288 inline int get_root() {
289   for (int r = 2;; r ++) {
290     int flag = 1;
291     for (int k = 1; 1ll * k * k <= mod; k ++) {
292       if (check(r, k) || check(r, (mod - 1) / k)) {
293     flag = 0;
294     break;
295       }
296     }
297     if (flag) return r;
298   }
299 }
300  
301 inline int get_log(int a, int x) {
302   static __gnu_pbds::gp_hash_table<int, int> ms;
303   ms.clear();
304   int m = int(sqrt(mod) + 0.5);
305   int t = 1, xx = Pow(a, m);
306   rep (i , 0 , mod / m + 1) {
307     if (ms.find(t) == ms.end()) ms[t] = i;
308     t = 1ll * t * xx % mod;
309   }
310   //cerr << ms.size() << endl;
311   t = Pow(a, mod - 2);
312   //assert(1ll * a * t % mod == 1);
313   rep (i , 0 , m) {
314     if (ms.find(x) != ms.end())
315       return ms[x] * m + i;
316     x = 1ll * x * t % mod;
317   }
318   assert(0);
319   return -1;
320 }
321  
322 const int maxn = 100007;
323  
324 int n, m;
325 ll x[maxn];
326 int y[maxn];
327  
328 int init(int l, int r, int _n, int P) {
329   //auto st = clock();
330   srand(time(0));
331   n = _n;
332   mod = P;
333   g = get_root();
334   for (;;) {
335     m = rnd() % (r - l + 1) + l;
336     int z = get_log(g, m);
337     if (z & 1) {
338       //cerr << "init time: " << (clock() - st) / 1000.0 << endl;
339       return m;
340     }
341   }
342 }
343  
344 void solve(int *A, int *B) {
345   //auto st = clock();
346  
347   int k2 = 1, k1 = mod - 1;
348   while (k1 % 2 == 0) k1 >>= 1, k2 <<= 1;
349   int N = n + 1 + (((n + 1) & 1) ^ 1);
350   int a = get_log(g, m), c = N % (mod - 1);
351   assert(Pow(g, a) == m);
352   int _a = Pow(a % k2, k2 / 2 - 1, k2);
353   assert(1ll * _a * a % k2 == 1);
354   for (int d = 1, i = 1; i <= n + N + 1; d += 2, i ++) {
355     int b = 1ll * c * d % k2 * _a % k2;
356     //int _d = Pow(g, 1ll * d * k1);
357     ll _d = 1ll * d * k1;
358     ll _b = 1ll * b * k1 % mod;
359     assert(1ll * a * _b % (k1 * k2) == 1ll * c * _d % (k1 * k2));
360     _d = Pow(g, _d);
361     x[i] = 1ll * _b * mod - 1ll * _d * (mod - 1);
362     if (x[i] < 0) x[i] += 1ll * mod * (mod - 1);
363     assert(x[i] % mod == _d);
364     assert(x[i] % (mod - 1) == _b);
365     assert(Pow(x[i], N) == Pow(m, x[i]));
366   }
367    
368   //cerr << "get x time: " << (clock() - st) / 1000.0 << endl;
369  
370   //st = clock();
371   get(n + N + 1, x, y);
372   //get(n, x, y);
373   //get(N + 1, x + n, y + n);
374   //cerr << "get y time: " << (clock() - st) / 1000.0 << endl;
375  
376   //st = clock();
377   auto F = Interpolation::interpolation(n + N + 1, x, y);
378   //cerr << "get F time: " << (clock() - st) / 1000.0 << endl;
379  
380   rep (i , 0 , n) A[i] = F[i];
381   rep (i , N , N + n) B[i - N] = F[i];
382 }
View Code

交互库:

  1 #include <bits/stdc++.h>
  2 
  3 #include "poly.h"
  4 
  5 using namespace std;
  6 
  7 #define ER_TOKEN "WA"
  8 #define WA_TOKEN "WA"
  9 #define HF_TOKEN "HF"
 10 #define AC_TOKEN "AC"
 11 #define ED_TOKEN "ED"
 12 
 13 inline static void halt(int value = 0)
 14 {
 15     printf(ED_TOKEN);
 16     exit(value);
 17 }
 18 
 19 namespace Variants {
 20 
 21     const char fin [] = "poly.in";
 22     const char fout[] = "poly.out";
 23 
 24     const int maxN = 100000 + 7;
 25 
 26     static int mod = 998244353, g = 3;
 27 
 28     static int n, L, R, m;
 29     static int A[maxN], B[maxN], resA[maxN], resB[maxN];
 30 
 31     inline static int Pow(int a, long long b)
 32     {
 33         int t = 1;
 34         for (/*b %= mod - 1*/; b; b >>= 1, a = 1ll * a * a % mod)
 35             if (b & 1)
 36                 t = 1ll * t * a % mod;
 37         return t;
 38     }
 39 
 40     inline static bool check(int x, int k)
 41     {
 42         return (mod - 1) % k == 0 && k != mod - 1 && Pow(x, k) == 1;
 43     }
 44 
 45     inline static void get_root()
 46     {
 47         for (g = 2;; g ++)
 48         {
 49             int flag = 1;
 50             for (int k = 1; 1ll * k * k <= mod; k ++)
 51                 if (check(g, k) || check(g, (mod - 1) / k))
 52                 {
 53                     flag = 0;
 54                     break;
 55                 }
 56             if (flag)
 57                 return;
 58         }
 59     }
 60 
 61     inline static void check(long long x)
 62     {
 63         static map<int, int> ms1, ms2;
 64 
 65         if (ms1[x % mod])
 66         {
 67             puts(ER_TOKEN);
 68             printf("%d mod P exists twice.\n", int(x % mod));
 69             halt(1);
 70         }
 71         ms1[x % mod] = 1;
 72         if (ms2[x % (mod - 1)])
 73         {
 74             puts(ER_TOKEN);
 75             printf("%d mod P-1 exists twice.\n", int(x % (mod-1)));
 76             halt(1);
 77         }
 78         ms2[x % (mod - 1)] = 1;
 79     }
 80 
 81 }
 82 
 83 using namespace Variants;
 84 
 85 namespace Interpol {
 86 
 87     #define iter(i, n) for (int i = 1; i <= n; ++i)
 88     #define iter0(i, n) for (int i = 0; i < n; ++i)
 89     #define forw(i, a, b) for (int i = a; i <= b; ++i)
 90     #define down(i, a, b) for (int i = b; i >= a; --i)
 91 
 92     #define reset(a, l, r) forw(i, l, r) a[i] = 0;
 93     #define NR 401000
 94 
 95     typedef vector<int> Poly;
 96 
 97     inline int pr(int a, int z) {
 98         int s = 1;
 99         while (z > 0) {
100             if (z % 2 == 1) s = 1ll * s * a % mod;
101             a = 1ll * a * a % mod;
102             z /= 2;
103         }
104         return s;
105     }
106 
107     inline int mod_inv(int a) { return pr(a, mod - 2); }
108 
109     void fft(int *a, int n, int ty) {
110         for (int i = n >> 1, j = 1, k; j < n - 1; ++j) {
111             if (i > j) swap(a[i], a[j]);
112             for (k = n >> 1; k <= i; k >>= 1) i ^= k;
113             i ^= k;
114         }
115 
116         for (int m = 2; m <= n; m <<= 1) {
117             int h = m >> 1, wm = pr(g, (mod - 1) / m * (ty == +1 ? 1 : (m - 1)));
118 
119             for (register int i = 0; i < n; i += m) {
120                 register int w = 1;
121                 for (int j = i; j < i + h; ++j) {
122                     register int u = a[j], v = 1ll * w * a[j + h] % mod;
123                     
124                     a[j] = (u + v) % mod;
125                     a[j + h] = (u - v + mod) % mod;
126                     w = 1ll * w * wm % mod;
127                 }
128             }
129         }
130 
131         if (ty == -1) {
132             int iv = mod_inv(n);
133             iter0(i, n) a[i] = 1ll * a[i] * iv % mod;
134         }
135     }
136 
137     ostream& operator<<(ostream &output, const Poly &a){  
138         output << "[";
139         int la = a.size();
140         iter0(i, la)
141             output << a[i] << (i + 1 == la ? ']' : ',');
142         return output;
143     }
144 
145     void upd(Poly &a) { while (!a.empty() && a.back() == 0) a.pop_back(); }
146 
147     inline Poly operator+(const Poly &a, const Poly &b) {
148         int la = a.size(), lb = b.size();
149         int lc = max(la, lb);
150         Poly c(lc);
151         iter0(i, lc) c[i] = ((i < la ? a[i] : 0) + (i < lb ? b[i] : 0)) % mod;
152         return upd(c), c;
153     }
154     inline void poly_multo(int a[], int b[], int N) {
155         fft(a, N, +1), fft(b, N, +1);
156         iter0(i, N) a[i] = 1ll * a[i] * b[i] % mod;
157         fft(a, N, -1);
158     }
159 
160     int ta[NR], tb[NR];
161 
162     Poly operator*(const Poly &a, const Poly &b) {
163         int la = a.size(), lb = b.size();
164         
165         Poly c(la + lb - 1);
166         
167         if (la + lb <= 100) {
168             iter0(i, la) iter0(j, lb) c[i + j] = (c[i + j] + 1ll * a[i] * b[j]) % mod;
169         } else {
170             int N;
171             for (N = 1; N < la + lb; N <<= 1);
172             iter0(i, N) {
173                 ta[i] = (i < la ? a[i] : 0);
174                 tb[i] = (i < lb ? b[i] : 0);
175             }
176             poly_multo(ta, tb, N);
177             iter0(i, la + lb - 1) c[i] = ta[i];
178         }
179         return upd(c), c;
180     }
181     int ccc = 0;
182     int ti[NR];
183 
184     void poly_inv(int *f, int *inv, int n) {
185         if (n == 0) {
186             inv[0] = mod_inv(f[0]);
187             return;
188         }
189         poly_inv(f, inv, n / 2);
190         static int t[140000];
191         int N = 1;
192         for (; N <= n * 2; N <<= 1);
193         iter0(i, N) t[i] = i <= n ? f[i] : 0; reset(inv, n / 2 + 1, N);
194         fft(inv, N, +1); fft(t, N, +1);
195         iter0(i, N) inv[i] = (2 + mod - 1ll * inv[i] * t[i] % mod) * inv[i] % mod;
196         fft(inv, N, -1);
197     }
198 
199     void poly_mod(int *a, int *b, int *c, int n, int m) {
200         if (n < m) {
201             iter0(i, m) c[i] = i <= n ? a[i] : 0;
202             return;
203         }
204         static int f[140000], g[140000];
205         if (n < 100) {
206             int invb = mod_inv(b[m]);
207             memcpy(f, a, sizeof(int) * (n + 1));
208             down(i, n, m) {
209                 int t = 1ll * f[i] * invb % mod;
210                 forw(j, 0, m) (f[i - j] += mod - 1ll * t * b[m - j] % mod) %= mod;
211             }
212             memcpy(c, f, sizeof(int) * m);
213             return;
214         }
215         
216         int N;
217         for (N = 1; N <= max(n, 2 * (n - m)) + 10; N <<= 1);
218         reset(g, 0, N);
219         
220         forw(i, 0, n - m) f[i] = i <= m ? b[m - i] : 0; reset(f, n - m + 1, N);
221         poly_inv(f, g, n - m); reset(g, n - m + 1, N);
222         forw(i, 0, n - m) f[i] = a[n - i];
223         poly_multo(g, f, N);
224         reset(g, n - m + 1, N);
225         reverse(g, g + n - m + 1);
226         forw(i, 0, m) f[i] = b[i]; reset(f, m + 1, N);
227         poly_multo(f, g, N);
228         iter0(i, m) c[i] = (a[i] + mod - f[i]) % mod;
229     }
230     int tr[NR];
231 
232     Poly operator%(const Poly &a, const Poly &b) {
233         
234         int la = a.size(), lb = b.size(), N;
235         Poly c(lb);
236         for (N = 1; N < la + lb; N <<= 1);
237         iter0(i, N) {
238             ta[i] = (i < la ? a[i] : 0);
239             tb[i] = (i < lb ? b[i] : 0);
240         }
241         poly_mod(ta, tb, tr, la - 1, lb - 1);
242         
243         iter0(i, lb) c[i] = tr[i];
244         iter0(i, N) tr[i] = 0;
245         upd(c);
246         
247         return c;
248     }
249     Poly t[NR], tt[NR];
250     int tsz, lc[NR], rc[NR];
251 
252 
253     void init(int &x, int l, int r, int *a) {
254         x = ++tsz;
255         if (l == r) {
256             t[x] = { (mod - a[l]) % mod, 1 };
257             return;
258         }
259         int mid = (l + r) / 2;
260         init(lc[x], l, mid, a);
261         init(rc[x], mid + 1, r, a);
262         t[x] = t[lc[x]] * t[rc[x]];
263     }
264 
265     int eval(const Poly &A, int x) {
266         int p = 1, res = 0;
267         for (auto it = A.begin(); it != A.end(); ++it) {
268             res = (res + 1ll * p * *it) % mod;
269             p = 1ll * p * x % mod;
270         }
271         return res;
272     }
273 
274     int pp[NR];
275 
276     Poly D(const Poly &a) {
277         int la = a.size();
278         Poly c(la - 1);
279         iter(i, la - 1) c[i - 1] = 1ll * i * a[i] % mod;
280         return c;
281     }
282 
283     void s2(int x, int l, int r, const Poly &f, int qX[], int ans[]) {
284         if (f.size() < 1000 || r - l + 1 <= 200) {
285             forw(i, l, r) pp[i] = 1;
286             for (auto it = f.begin(); it != f.end(); ++it) {
287                 forw(i, l, r) {
288                     ans[i] = (ans[i] + 1ll * pp[i] * *it) % mod;
289                     pp[i] = 1ll * pp[i] * qX[i] % mod;
290                 }
291             }
292             return;
293         }
294 
295         int mid = (l + r) / 2;
296         s2(lc[x], l, mid, f % t[lc[x]], qX, ans);
297         s2(rc[x], mid + 1, r, f % t[rc[x]], qX, ans);
298     }
299     int root;
300 
301     void evaluation(const Poly &f, bool inited, int qX[], int ans[], int m) {
302         if (!inited) {
303             tsz = 0;
304             init(root, 1, m, qX);
305         }
306         s2(root, 1, m, f, qX, ans);
307         
308     }
309 
310     int px[NR], py[NR], qx[NR], qy[NR], Q[NR], n, m;
311 
312     Poly s1(int x, int l, int r) {
313         if (l == r) {
314             Poly tmp = { (int) (1ll * py[l] * mod_inv(Q[l]) % mod) };
315             return tmp;
316         }
317         int mid = (l + r) / 2;
318         Poly L = s1(lc[x], l, mid), R = s1(rc[x], mid + 1, r);
319         return L * t[rc[x]] + R * t[lc[x]];
320     }
321 
322 }
323 
324 int get(long long x)
325 {
326     check(x);
327     int res = 0, t = 1, m = Pow(Variants::m, x);
328     x %= mod;
329     for (int i = 0; i <= n; i ++)
330         {
331             (res += (1ll * m * B[i] % mod + A[i]) * t % mod) %= mod;
332             t = 1ll * t * x % mod;
333         }
334     return res;
335 }
336 
337 void get(int m, long long *X, int *Y)
338 {
339     static int x[maxN], ya[maxN], yb[maxN];
340 
341     //auto st = clock();
342 
343     for (int i = 1; i <= m; i ++)
344     {
345         check(X[i]);
346         x[i] = X[i] % mod;
347     }
348 
349     Interpol::Poly a;
350     a.resize(n + 1);
351 
352     for (int i = 0; i <= n; i ++)
353         a[i] = A[i];
354     Interpol::evaluation(a, false, x, ya, m);
355 
356     for (int i = 0; i <= n; i ++)
357         a[i] = B[i];
358     Interpol::evaluation(a, false, x, yb, m);
359 
360     //cerr << "evaluate time: " << (clock() - st) / 1000.0 << endl;
361 
362     //st = clock();
363     for (int i = 1; i <= m; i ++)
364         Y[i] = (1ll * Pow(Variants::m, X[i]) * yb[i] % mod + ya[i]) % mod;
365     //cerr << "get Y[] time: " << (clock() - st) / 1000.0 << endl;
366 }
367 
368 int main()
369 {
370     using namespace Variants;
371     freopen(fin , "r", stdin);
372     freopen(fout, "w", stdout);
373     
374     scanf("%d%d%d%d", &n, &L, &R, &mod);
375     for (int i = 0; i <= n; i ++)
376         scanf("%d", &A[i]);
377     for (int i = 0; i <= n; i ++)
378         scanf("%d", &B[i]);
379     get_root();
380 
381     m = init(L, R, n, mod);
382     if (!(L <= m && m <= R))
383     {
384         puts(WA_TOKEN);
385         printf("m=%d is not in [%d,%d]\n", m, L, R);
386         return 1;
387     }
388     solve(resA, resB);
389 
390     int cntA = 0, cntB = 0;
391     for (int i = 0; i <= n; i ++)
392     {
393         cntA += (A[i] != resA[i] % mod);
394         cntB += (B[i] != resB[i] % mod);
395     }
396 
397 /*
398     for (int i = 0; i <= n; i ++)
399         cerr << resA[i] << " "; cerr << endl;
400     for (int i = 0; i <= n; i ++)
401         cerr << resB[i] << " "; cerr << endl;
402 */
403 
404     if (cntA == 0 && cntB == 0)
405         puts(AC_TOKEN);
406     else if (cntA == 0 || cntB == 0)
407     {
408         puts(HF_TOKEN);
409         char c = cntA ? 'B' : 'A';
410         printf("You answer polynomial %c correctly, the other one has %d different coefficients.\n", c, cntA + cntB);
411         halt(1);
412     }
413     else
414     {
415         puts(WA_TOKEN);
416         printf("Your polynomial A and B has %d and %d different coefficients.\n", cntA, cntB);
417         halt(1);
418     }
419 
420     halt();
421     return 0;
422 }
View Code

 

在大佬们看来的水题我才考这么几分,果然还是我太菜了呀。

posted @ 2018-03-11 20:48  Cmd2001  阅读(239)  评论(0编辑  收藏  举报