北京集训:20180310

北京集训的第一天,我完美爆零......
这其中的经历,十分有趣呢。

T1:

这题一看就是先猜一个性质然后利用他去求解。
如果我们知道怎么插入,怎么判定的话,可以线段树分治的说。
然后我猜了一个结论:如果稳定,则一定有一个x的四联通块能同时通向上下左右边界。
乍一看是对的,实际上这个东西充分,但不必要。
考虑3*3的网格图,我们染色左下角三个点,再染色右上角三个点,结果应该是稳定的。
然后这个算法就错了。
问题是由于我太菜了,故考场上并没有想到这个反例......
正解的确是线段树分治,然而他是用角度推的。
考虑对于一个四边形的四个定点,每个点在左上角的那个角,显然对角线的角和相同。
而如果一个格子为x,则他右下角和左上角的角度均为90度,相当于让另外两个角必须满足某些条件。
而如果这个条件让整个图都被限制的话,显然就固定了。
现在我们可以做什么?O(nmq)暴力。
然而正解要更加优美:
显然我们可以用第一行的所有角度和第一列的所有角度算出所有角,所以限制就相当于是行列连边。
经典的二分图模型啦。
然后用可回退并查集维护是否左右行列都在一个联通块里就好了QwQ。
考场爆零代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=9e6+1e2,maxl=3e3+1e2,maxq=1e5+1e2;
  9 const int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
 10 
 11 char in[maxl][maxl],now[maxl][maxl];
 12 int tim[maxl][maxl],ans[maxq];
 13 int l[maxq<<3],r[maxq<<3],lson[maxq<<3],rson[maxq<<3],cnt;
 14 int fa[maxn],siz[maxn],sta[maxn];
 15 int n,m,q;
 16 int pp;
 17 
 18 struct ONode {
 19     int x,y;
 20 };
 21 vector<ONode> ns[maxq<<3];
 22 
 23 struct MemNode {
 24     int *dst,val;
 25     MemNode() {}
 26     MemNode(int &x) { dst = &x , val = x; }
 27     inline void res() {
 28         *dst = val;
 29     }
 30 }stk[maxn];
 31 int top;
 32 
 33 inline int findfa(int x) {
 34     return fa[x] == x ? x : findfa(fa[x]);
 35 }
 36 inline bool merge(int x,int y) {
 37     x = findfa(x) , y = findfa(y);
 38     if( x == y ) return 0;
 39     if( siz[x] < siz[y] ) swap(x,y);
 40     if( pp != 1 ) stk[++top] = MemNode(siz[x]) , stk[++top] = MemNode(fa[y]) , stk[++top] = MemNode(sta[x]);
 41     fa[y] = x , siz[x] += siz[y] , sta[x] |= sta[y];
 42     return sta[x] == 15;
 43 }
 44 
 45 inline void reset(int ltop) {
 46     while( top > ltop ) stk[top].res() , --top;
 47 }
 48 inline int cov(int x,int y) {
 49     return m * --x + y;
 50 }
 51 inline int operat(int x,int y) {
 52     int ret = 0;
 53     now[x][y] = 'x';
 54     ret |= ( sta[findfa(cov(x,y))] == 15 );
 55     for(int i=0;i<4;i++) {
 56         const int tx = x + dx[i] , ty = y + dy[i];
 57         if( 0 < tx && tx <= n && 0 < ty && ty <= m && now[tx][ty] == 'x' ) ret |= merge(cov(x,y),cov(tx,ty));
 58     }
 59     return ret;
 60 }
 61 
 62 inline void build(int pos,int ll,int rr) {
 63     l[pos] = ll , r[pos] = rr;
 64     if( ll == rr ) return;
 65     const int mid = ( ll + rr ) >> 1;
 66     build(lson[pos]=++cnt,ll,mid) , build(rson[pos]=++cnt,mid+1,rr);
 67 }
 68 inline void insert(int pos,int ll,int rr,const ONode &o) {
 69     if( ll <= l[pos] && r[pos] <= rr ) {
 70         ns[pos].push_back(o);
 71         return;
 72     } const int mid = ( l[pos] + r[pos] ) >> 1;
 73     if( rr <= mid ) insert(lson[pos],ll,rr,o);
 74     else if( ll > mid ) insert(rson[pos],ll,rr,o);
 75     else insert(lson[pos],ll,rr,o) , insert(rson[pos],ll,rr,o);
 76 }
 77 inline void dfs(int pos,int stable) {
 78     pp = pos;
 79     const int memtop = top;
 80     for(unsigned i=0;i<ns[pos].size();i++) stable |= operat(ns[pos][i].x,ns[pos][i].y);
 81     if( l[pos] == r[pos] ) {
 82         ans[l[pos]] = stable;
 83     }
 84     else dfs(lson[pos],stable) , dfs(rson[pos],stable);
 85     if( pos != 1 ) {
 86         reset(memtop);
 87         for(unsigned i=0;i<ns[pos].size();i++) now[ns[pos][i].x][ns[pos][i].y] = 0;
 88     }
 89 }
 90 
 91 int main() {
 92     static int q;
 93     scanf("%d%d%d",&n,&m,&q);
 94     for(int i=1;i<=n;i++) {
 95         scanf("%s",in[i]+1);
 96         for(int j=1;j<=m;j++) if( in[i][j] == 'x' ) tim[i][j] = 1;
 97     }
 98     build(cnt=1,1,q+1);
 99     for(int i=1,x,y;i<=q;i++) {
100         scanf("%d%d",&x,&y);
101         if( tim[x][y] ) {
102             insert(1,tim[x][y],i,(ONode){x,y}) , tim[x][y] = 0;
103         }
104         else tim[x][y] = i+1;
105     }
106     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if( tim[i][j] ) {
107         insert(1,tim[i][j],q+1,(ONode){i,j});
108     }
109     for(int i=1;i<=n;i++)
110         for(int j=1;j<=m;j++) {
111             const int c = cov(i,j);
112             fa[c] = c , siz[c] = 1;
113             if( i == 1 ) sta[c] |= 1;
114             if( j == 1 ) sta[c] |= 2;
115             if( i == n ) sta[c] |= 4;
116             if( j == m ) sta[c] |= 8;
117         }
118     dfs(1,0);
119     for(int i=1;i<=q+1;i++) puts(ans[i]?"S":"U");
120     return 0;
121 }
View Code

考后AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<stack>
 7 #define debug cout
 8 using namespace std;
 9 const int maxn=9e6+1e2,maxl=3e3+1e2,maxq=3e5+1e2;
10 
11 char in[maxl][maxl];
12 int tim[maxl][maxl];
13 int l[maxq<<2],r[maxq<<2],lson[maxq<<2],rson[maxq<<2],cnt;
14 int fa[maxn],siz[maxn];
15 int ans[maxq];
16 int n,m;
17 
18 struct Node {
19     int x,y;
20 };
21 vector<Node> ns[maxq<<2];
22 struct StkNode {
23     int *dst,val;
24     StkNode() {}
25     StkNode(int &x) { dst = &x , val = x; }
26     inline void res() { *dst = val ; }
27 }stk[maxq<<2];
28 int top;
29 
30 inline int findfa(int x) {
31     return fa[x] == x ? x : findfa(fa[x]);
32 }
33 inline void merge(int x,int y,int pos) {
34     x = findfa(x) , y = findfa(y);
35     if( x == y ) return;
36     if( siz[x] < siz[y] ) swap(x,y);
37     if( pos != 1 ) stk[++top] = StkNode(fa[y]) , stk[++top] = StkNode(siz[x]);
38     fa[y] = x , siz[x] += siz[y];
39 }
40 inline void reset(int last) {
41     while( top > last ) stk[top--].res();
42 }
43 
44 inline void build(int pos,int ll,int rr) {
45     l[pos] = ll , r[pos] = rr;
46     if( ll == rr ) return;
47     const int mid = ( ll + rr ) >> 1;
48     build(lson[pos]=++cnt,ll,mid) , 
49     build(rson[pos]=++cnt,mid+1,rr) ;
50 }
51 inline void insert(int pos,int ll,int rr,const Node &o) {
52     if( ll <= l[pos] && r[pos] <= rr ) return ns[pos].push_back(o);
53     const int mid = r[lson[pos]];
54     if( rr <= mid ) return insert(lson[pos],ll,rr,o);
55     if( ll > mid ) return insert(rson[pos],ll,rr,o);
56     insert(lson[pos],ll,rr,o) , 
57     insert(rson[pos],ll,rr,o) ;
58 }
59 inline void dfs(int pos) {
60     const int mtop = top;
61     for(unsigned i=0;i<ns[pos].size();i++) merge(ns[pos][i].x,ns[pos][i].y+n,pos);
62     if( l[pos] == r[pos] ) ans[l[pos]] = ( siz[findfa(1)] == n + m );
63     else dfs(lson[pos]) , dfs(rson[pos]);
64     if( pos != 1 ) reset(mtop);
65 }
66 
67 int main() {
68     static int q;
69     scanf("%d%d%d",&n,&m,&q) , memset(tim,-1,sizeof(tim));
70     for(int i=1;i<=n;i++) {
71         scanf("%s",in[i]+1);
72         for(int j=1;j<=m;j++) if( in[i][j] == 'x' ) tim[i][j] = 0;
73     }
74     build(cnt=1,0,q);
75     for(int i=1,x,y;i<=q;i++) {
76         scanf("%d%d",&x,&y);
77         if( ~tim[x][y] ) insert(1,tim[x][y],i-1,(Node){x,y}) , tim[x][y] = -1;
78         else tim[x][y] = i;
79     }
80     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if( ~tim[i][j] ) insert(1,tim[i][j],q,(Node){i,j});
81     for(int i=1;i<=n+m;i++) fa[i] = i , siz[i] = 1;
82     dfs(1);
83     for(int i=0;i<=q;i++) puts(ans[i]?"S":"U");
84     return 0;
85 }
View Code


T2:


前两个测试点可以大力状压哈希bfs(不,大力bfs是过不去第二个测试点的)。
然后我们考虑分析一发:
首先我们只有三根柱子(废话)。
考虑最大的位置不对的盘子,我们一定要把他从一根柱子移动到另一根。
也就是说,我们需要让他所在的柱子为只有他,他需要到的柱子为空。
其他的盘子呢?必须都移到剩下的一个柱子上啊。这个步数大力计算一下就好了。
然后我们移动了最大的盘子,现在我们有一摞盘子和他们需要的地方。
一个一个摆放到位就可以了,反正(大概)只有一种不走重复步的方案吧。
接着你会发现你会WA,你过不了样例。
因为样例的最优解是把最大的盘子先放到中间。
好,这也是一种策略,我们把第一步的这种方式也考虑进去,反正接下来对一摞盘子的分析一定是对的。
关于我为什么爆零?考场上以为1是最大的盘子,然后直接贪心过了样例,自然也没有想第二种情况啦......
其实更正了看错题的问题还是有60分的。
考场爆零代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<map>
  7 #include<queue>
  8 #define lli long long int
  9 #define ulli unsigned long long
 10 #define debug cout
 11 using namespace std;
 12 const int maxn=1e6+1e2,mod=998244353;
 13 const int base=17;
 14 const int maxl=20;
 15 
 16 int n;
 17 
 18 namespace Sol {
 19     int st[3][maxn],ed[3][maxn],now[3][maxn],n;
 20     lli pows[maxn];
 21     
 22     inline int findmx(int sou[3][maxn]) {
 23         int ret = -1;
 24         for(int i=0;i<3;i++)
 25             if( sou[i][0] && ( ret == -1 || sou[i][sou[i][0]] < sou[ret][sou[ret][0]] ) ) ret = i;
 26         return ret;
 27     }
 28     inline int solve_merge(int siz,int tar) {
 29         int xp = findmx(st);
 30         while( siz && xp == tar ) st[xp][st[xp][0]] = 0 , st[xp][0]-- , siz-- , xp = findmx(st);
 31         if( !siz ) return 0;
 32         st[xp][st[xp][0]] = 0 , st[xp][0]--;
 33         const int nt = 3 - xp - tar;
 34         return ( solve_merge(siz-1,nt) + 1 + pows[siz-1] ) % mod;
 35     }
 36     
 37     inline void solve() {
 38         int ms,me,siz=n;
 39         lli ans = 0;
 40         while( siz ) {
 41             ms = findmx(st) , me = findmx(ed);
 42             if( ms == me ) {
 43                 st[ms][st[ms][0]] = 0 , --st[ms][0];
 44                 ed[me][ed[me][0]] = 0 , --ed[me][0];
 45                 --siz;
 46             } else break;
 47         }
 48         if( !siz ) {
 49             puts("0");
 50             return;
 51         }
 52         int ftar = 3 - ms - me;
 53         st[ms][st[ms][0]] = 0 , --st[ms][0];
 54         ed[me][ed[me][0]] = 0 , --ed[me][0];
 55         --siz;
 56         ans = solve_merge(siz,ftar) + 1;
 57         //debug<<"inital ans = "<<ans<<endl;
 58         while( siz ) {
 59             while( siz && ( me = findmx(ed) ) == ftar ) {
 60                  ed[me][ed[me][0]] = 0 , --ed[me][0];
 61                  --siz;
 62             }
 63             if( !siz ) break;
 64             ans = ( ans + pows[siz-1] + 1 ) % mod;
 65             ftar = 3 - me - ftar;
 66             ed[me][ed[me][0]] = 0 , --ed[me][0] , --siz;
 67         }
 68         ans = ( ans + mod ) % mod;
 69         printf("%lld\n",ans);
 70     }
 71     int main() {
 72         for(int i=1;i<=n;i++) pows[i] = ( ( pows[i-1] << 1 ) | 1 ) % mod;
 73         for(int i=0;i<3;i++) {
 74             scanf("%d",st[i]);
 75             for(int j=1;j<=st[i][0];j++) scanf("%d",st[i]+j);
 76             reverse(st[i]+1,st[i]+1+st[i][0]);
 77         }
 78         for(int i=0;i<3;i++) {
 79             scanf("%d",ed[i]);
 80             for(int j=1;j<=ed[i][0];j++) scanf("%d",ed[i]+j);
 81             reverse(ed[i]+1,ed[i]+1+ed[i][0]);
 82         }
 83         solve();
 84         return 0;
 85     }
 86 }
 87 
 88 namespace Force {
 89     struct Statement {
 90         bitset<maxl> s[3];
 91         inline ulli h() const {
 92             ulli ret = 0;
 93             for(int i=0;i<3;i++)
 94                 for(int j=1;j<=n;j++)
 95                     ret = ret * base + ( j * s[i][j] );
 96             return ret;
 97         }
 98         inline void findtop(int* ret) const {
 99             for(int i=0;i<3;i++) {
100                 ret[i] = 0;
101                 for(int j=n;j;j--)
102                     if( s[i][j] ) {
103                         ret[i] = j;
104                         break;
105                     }
106                 }
107         }
108     }st,ed;
109     
110     map<ulli,int> mp;
111     queue<pair<Statement,int> > q;
112     ulli tar;
113     int ans;
114     
115     inline void extend(const Statement &x,const int step) {
116         Statement nxt = x;
117         int tops[3];
118         x.findtop(tops);
119         for(int i=0;i<3;i++)
120             for(int j=0;j<3;j++)
121                 if( i != j && tops[j] < tops[i]) { // move from i to j .
122                     nxt.s[i][tops[i]] = 0 , nxt.s[j][tops[i]] = 1;
123                     ulli h = nxt.h();
124                     if( h == tar ) {
125                         ans = step + 1;
126                         return;
127                     } else if( !mp.count(h) ) {
128                         mp[h] = step + 1;
129                         q.push(make_pair(nxt,step+1));
130                     }
131                     nxt.s[i][tops[i]] = 1 , nxt.s[j][tops[i]] = 0;
132                 }
133     }
134     
135     int main() {
136         ans = -1;
137         if( n <= 15 ) {
138             for(int i=0,t,x;i<3;i++) {
139                 scanf("%d",&t);
140                 while(t--) scanf("%d",&x) , st.s[i][x] = 1;
141             }
142             ulli h = st.h();
143             for(int i=0,t,x;i<3;i++) {
144                 scanf("%d",&t);
145                 while(t--) scanf("%d",&x) , ed.s[i][x] = 1;
146             }
147             tar = ed.h();
148             q.push(make_pair(st,0)) , mp[h] = 0;
149             while( q.size() && !~ans ) {
150                 extend(q.front().first,q.front().second) , q.pop();
151             }
152             if( h == tar ) return puts("0"),0;
153             printf("%d\n",ans);
154         } else {
155             int ans = 1;
156             while(n--) ans = (long long) ans * 2 % 998244353;
157             ans = ( ans - 1 + 998244353 ) % 998244353;
158             printf("%d\n",ans);
159         }
160         return 0;
161     }
162 }
163 
164 int main() {
165     scanf("%d",&n);
166     if( n <= 15 ) Force::main();
167     else Sol::main();
168     return 0;
169 }
View Code

稍加修改的60分代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<map>
  7 #include<queue>
  8 #define lli long long int
  9 #define ulli unsigned long long
 10 #define debug cout
 11 using namespace std;
 12 const int maxn=1e6+1e2,mod=998244353;
 13 const int base=17;
 14 const int maxl=20;
 15 
 16 int n;
 17 
 18 namespace Sol {
 19     int st[3][maxn],ed[3][maxn],now[3][maxn];
 20     lli pows[maxn];
 21     
 22     inline int findmx(int sou[3][maxn]) {
 23         int ret = -1;
 24         for(int i=0;i<3;i++)
 25             if( sou[i][0] && ( ret == -1 || sou[i][sou[i][0]] < sou[ret][sou[ret][0]] ) ) ret = i;
 26         return ret;
 27     }
 28     inline int solve_merge(int siz,int tar) {
 29         int xp = findmx(st);
 30         while( siz && xp == tar ) st[xp][st[xp][0]] = 0 , st[xp][0]-- , siz-- , xp = findmx(st);
 31         if( !siz ) return 0;
 32         st[xp][st[xp][0]] = 0 , st[xp][0]--;
 33         const int nt = 3 - xp - tar;
 34         return ( solve_merge(siz-1,nt) + 1 + pows[siz-1] ) % mod;
 35     }
 36     
 37     inline void solve() {
 38         int ms,me,siz=n;
 39         lli ans = 0;
 40         while( siz ) {
 41             ms = findmx(st) , me = findmx(ed);
 42             //debug<<"ms = "<<ms<<"me = "<<me<<endl;
 43             if( ms == me ) {
 44                 st[ms][st[ms][0]] = 0 , --st[ms][0];
 45                 ed[me][ed[me][0]] = 0 , --ed[me][0];
 46                 --siz;
 47             } else break;
 48         }
 49         if( !siz ) {
 50             puts("0");
 51             return;
 52         }
 53         int ftar = 3 - ms - me;
 54         st[ms][st[ms][0]] = 0 , --st[ms][0];
 55         ed[me][ed[me][0]] = 0 , --ed[me][0];
 56         --siz;
 57         ans = solve_merge(siz,ftar) + 1;
 58         //debug<<"inital ans = "<<ans<<endl;
 59         while( siz ) {
 60             while( siz && ( me = findmx(ed) ) == ftar ) {
 61                  ed[me][ed[me][0]] = 0 , --ed[me][0];
 62                  --siz;
 63             }
 64             if( !siz ) break;
 65             ans = ( ans + pows[siz-1] + 1 ) % mod;
 66             ftar = 3 - me - ftar;
 67             ed[me][ed[me][0]] = 0 , --ed[me][0] , --siz;
 68         }
 69         ans = ( ans + mod ) % mod;
 70         printf("%lld\n",ans);
 71     }
 72     int main() {
 73         for(int i=1;i<=n;i++) pows[i] = ( ( pows[i-1] << 1 ) | 1 ) % mod;
 74         for(int i=0;i<3;i++) {
 75             scanf("%d",st[i]);
 76             for(int j=1;j<=st[i][0];j++) scanf("%d",st[i]+j) , st[i][j] = n - st[i][j] + 1;
 77             //reverse(st[i]+1,st[i]+1+st[i][0]);
 78         }
 79         for(int i=0;i<3;i++) {
 80             scanf("%d",ed[i]);
 81             for(int j=1;j<=ed[i][0];j++) scanf("%d",ed[i]+j) , ed[i][j] = n - ed[i][j] + 1;
 82             //reverse(ed[i]+1,ed[i]+1+ed[i][0]);
 83         }
 84         solve();
 85         return 0;
 86     }
 87 }
 88 
 89 namespace Force {
 90     struct Statement {
 91         bitset<maxl> s[3];
 92         inline ulli h() const {
 93             ulli ret = 0;
 94             for(int i=0;i<3;i++)
 95                 for(int j=1;j<=n;j++)
 96                     ret = ret * base + ( j * s[i][j] );
 97             return ret;
 98         }
 99         inline void findtop(int* ret) const {
100             for(int i=0;i<3;i++) {
101                 ret[i] = 0;
102                 for(int j=n;j;j--)
103                     if( s[i][j] ) {
104                         ret[i] = j;
105                         break;
106                     }
107                 }
108         }
109     }st,ed;
110     
111     map<ulli,int> mp;
112     queue<pair<Statement,int> > q;
113     ulli tar;
114     int ans;
115     
116     inline void extend(const Statement &x,const int step) {
117         Statement nxt = x;
118         int tops[3];
119         x.findtop(tops);
120         for(int i=0;i<3;i++)
121             for(int j=0;j<3;j++)
122                 if( i != j && tops[j] < tops[i]) { // move from i to j .
123                     nxt.s[i][tops[i]] = 0 , nxt.s[j][tops[i]] = 1;
124                     ulli h = nxt.h();
125                     if( h == tar ) {
126                         ans = step + 1;
127                         return;
128                     } else if( !mp.count(h) ) {
129                         mp[h] = step + 1;
130                         q.push(make_pair(nxt,step+1));
131                     }
132                     nxt.s[i][tops[i]] = 1 , nxt.s[j][tops[i]] = 0;
133                 }
134     }
135     
136     int main() {
137         ans = -1;
138         if( n <= 15 ) {
139             for(int i=0,t,x;i<3;i++) {
140                 scanf("%d",&t);
141                 while(t--) scanf("%d",&x) , st.s[i][n-x+1] = 1;
142             }
143             ulli h = st.h();
144             for(int i=0,t,x;i<3;i++) {
145                 scanf("%d",&t);
146                 while(t--) scanf("%d",&x) , ed.s[i][n-x+1] = 1;
147             }
148             tar = ed.h();
149             q.push(make_pair(st,0)) , mp[h] = 0;
150             while( q.size() && !~ans ) {
151                 extend(q.front().first,q.front().second) , q.pop();
152             }
153             if( h == tar ) return puts("0"),0;
154             printf("%d\n",ans);
155         } else {
156             int ans = 1;
157             while(n--) ans = (long long) ans * 2 % 998244353;
158             ans = ( ans - 1 + 998244353 ) % 998244353;
159             printf("%d\n",ans);
160         }
161         return 0;
162     }
163 }
164 
165 int main() {
166     scanf("%d",&n);
167     if( n < 15 ) Force::main();
168     else Sol::main();
169     return 0;
170 }
View Code

考后AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define lli long long int
 6 using namespace std;
 7 const int maxn=1e6+1e2;
 8 const int mod=998244353;
 9 
10 int st[maxn],ed[maxn],way1[maxn],way2[maxn];
11 lli ans;
12 
13 inline void calc(int* dst,const int* sou,int pos,int tar) {
14     if( !pos ) return;
15     if( sou[pos] == tar ) return calc(dst,sou,pos-1,tar);
16     ++dst[pos-1] , calc(dst,sou,pos-1,6-tar-sou[pos]);
17 }
18 inline void fix(int* dst,int len) {
19     for(int i=0;i<len;i++)
20         dst[i+1] += dst[i] >> 1 , dst[i] &= 1;
21 }
22 inline bool cmp(int* lhs,int* rhs,int len) {
23     for(int i=len;~i;i--) if( lhs[i] != rhs[i] ) return lhs[i] < rhs[i];
24     return 0;
25 }
26 inline lli getans(int* sou,int len) {
27     lli ret = 0;
28     for(int i=len;~i;i--) ret = ( ( ret << 1 ) + sou[i] ) % mod;
29     return ret;
30 }
31 
32 int main() {
33     static int n,siz;
34     scanf("%d",&n),siz=n;
35     for(int i=1,p,x;i<=3;i++) {
36         scanf("%d",&p);
37         while(p--) scanf("%d",&x) , st[x] = i;
38     }
39     for(int i=1,p,x;i<=3;i++) {
40         scanf("%d",&p);
41         while(p--) scanf("%d",&x) , ed[x] = i;
42     }
43     while( st[siz] == ed[siz] ) --siz;
44     if( !siz ) return puts("0"),0;
45     calc(way1,st,siz-1,6-st[siz]-ed[siz]) , calc(way1,ed,siz-1,6-st[siz]-ed[siz]) , ++*way1;
46     calc(way2,st,siz-1,ed[siz]) , calc(way2,ed,siz-1,st[siz]) , ++*way2 , ++way2[siz-1];
47     fix(way1,n+3) , fix(way2,n+3);
48     ans = cmp(way1,way2,n+3) ? getans(way1,n+3) : getans(way2,n+3);
49     printf("%lld\n",ans);
50     return 0;
51 }
View Code


T3:


这一看就是神仙题啊,这东西人干事?
以下是官方的题解:

看不懂题解的我只好写了一个60分大力反演,弃坑了。
60分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define lli long long int
 7 #define debug cout
 8 using namespace std;
 9 const int maxn=1e6+1e2;
10 const int mod=998244353;
11 
12 int bas[maxn],tim[maxn],mu[maxn];
13 int n,D,L,R;
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 int gcd(int x,int y) {
24     if( ! ( x && y ) ) return x | y;
25     register int t;
26     while( ( t = x % y ) )
27         x = y , y = t;
28     return y;
29 }
30 
31 inline void pre() {
32     bas[1] = tim[1] = 1;
33     for(int i=2;i<=n;i++) {
34         if( !bas[i] ) for(lli j=i,cnt=1;j<=n;j*=i,++cnt) bas[j] = i , tim[j] = cnt;
35     }
36 }
37 inline void sieve() {
38     static int prime[maxn],cnt;
39     static char vis[maxn];
40     mu[1] = 1;
41     for(int i=2;i<=n;i++) {
42         if( !vis[i] ) prime[++cnt] = i , mu[i] = -1;
43         for(int j=1;j<=cnt&&(lli)i*prime[j]<=n;j++) {
44             const int tar = i * prime[j];
45             vis[tar] = 1;
46             if( ! ( i % prime[j]) ) break;
47             mu[tar] = -mu[i];
48         }
49     }
50 }
51 
52 inline lli force_g(int x,int sqt) {
53     int g = gcd( sqt , tim[x] );
54     return fastpow(fastpow(bas[x],tim[x]/g),sqt/g);
55 }
56 inline lli force(int x) {
57     lli ret = 0;
58     const int lim = (int) ( log2(x) * D + 1e-6 );
59     for(int i=D;i<=lim;i+=D) {
60         for(int j=1;j*i<=lim;j++)
61             ret += mu[i/D] * mu[j] * fastpow(j,D) * force_g(x,i*j) % mod ,
62             ret %= mod;
63     }
64     return ret;
65 }
66 
67 int main() {
68     static lli ans;
69     scanf("%d%d%d%d",&n,&D,&L,&R) , pre() , sieve();
70     for(int i=L;i<=R;i++) ( ans += force(i) ) %= mod;
71     ans = ( ans % mod + mod ) % mod;
72     printf("%lld\n",ans);
73     return 0;
74 }
View Code

然后把神仙写的标程丢上来好了,反正我已经凉了。
神仙题的std:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 typedef long long lint;
  5 typedef long double db;
  6 const int N = 500010, MO = 998244353;
  7  
  8 inline int add(int a,int b) { return (a+b)%MO; }
  9 inline int mul(int a,int b) { return (lint)a*b%MO; }
 10 inline int powmod(int a,int b) 
 11 {
 12     int s = 1;
 13     for(;b;b>>=1,a=mul(a,a)) if(b&1) s = mul(s,a);
 14     return s;
 15 }
 16  
 17 int n,D,L,R;
 18 int sk[N],mu[N],c[N],pr[N],np[N],ps;
 19  
 20 void pre()
 21 {
 22     int i,j; np[1] = 1, mu[1] = 1;
 23     for(i=2;i<N;i++)
 24     {
 25         if(!np[i]) pr[++ps] = i, mu[i] = MO-1;
 26         for(j=1;j<=ps&&i*pr[j]<N;j++)
 27         {
 28             np[i*pr[j]] = 1;
 29             if(i%pr[j]==0) break;
 30             mu[i*pr[j]] = (MO-mu[i])%MO;
 31         }
 32     }
 33     for(i=1;i<=33;i++)
 34     {
 35         for(j=1;j<=i;j++) if(i%j==0)
 36             c[i] = add(c[i],mul(mul(mu[j],mu[i/j]),powmod(i/j,D)));
 37     }
 38 }
 39  
 40 int sum(int k,int l,int r)
 41 {
 42     if(l>r) return 0;
 43     k++;
 44     int s = 0, top = min(k,r);
 45     int i,j;
 46     sk[1] = 1;
 47     for(i=2;i<=top;i++)
 48     {
 49         if(!np[i]) sk[i] = powmod(i,k-1);
 50         for(j=1;j<=ps&&pr[j]<=i&&i*pr[j]<=top;j++)
 51         {
 52             sk[i*pr[j]] = mul(sk[i],sk[pr[j]]);
 53             if(i%pr[j]==0) break;
 54         }
 55     }
 56     if(r<=k)
 57     {
 58         for(int i=l;i<=r;i++) 
 59             s = add(s,sk[i]);
 60         return s;
 61     }
 62     for(i=1;i<=k;i++) sk[i] = add(sk[i],sk[i-1]);
 63     static int fc[N],iv[N],ml[N],mr[N];
 64     fc[0] = 1, ml[0] = 1, mr[k] = 1;
 65     for(i=1;i<=k;i++) fc[i] = mul(fc[i-1],i), ml[i] = mul(ml[i-1],r-k+i-1);
 66     iv[k] = powmod(fc[k],MO-2);
 67     for(i=k-1;i>=0;i--) mr[i] = mul(mr[i+1],r-k+i+1), iv[i] = mul(iv[i+1],i+1);
 68     for(i=0;i<=k;i++) s = add(s,(MO+(i&1?-1:1)*mul(sk[k-i],mul(mul(ml[i],mr[i]),mul(iv[i],iv[k-i]))))%MO);
 69  
 70     l--;
 71     for(i=1;i<=k;i++) ml[i] = mul(ml[i-1],l-k+i-1);
 72     for(i=k-1;i>=0;i--) mr[i] = mul(mr[i+1],l-k+i+1);
 73     for(i=0;i<=k;i++) s = add(s,(MO-(i&1?-1:1)*mul(sk[k-i],mul(mul(ml[i],mr[i]),mul(iv[i],iv[k-i]))))%MO);
 74     return s;
 75 }
 76  
 77 inline int rtceil(int a,int b)
 78 {
 79     int x = pow(a,1/(db)b);
 80     while(pow(x,b)>a) x--;
 81     while(pow(x,b)<a) x++;
 82     return x;
 83 }
 84  
 85 inline int rtfloor(int a,int b)
 86 {
 87     int x = pow(a,1/(db)b);
 88     while(pow(x,b)<a) x++;
 89     while(pow(x,b)>a) x--;
 90     return x;
 91 }
 92  
 93 int calcg(int m)
 94 {
 95     int s = 0;
 96     for(int k=1;k<=m;k++) if(m%k==0)
 97     {
 98         int x = max(rtceil(L,k),(int)ceil(pow(2,m/k/(db)D)));
 99         int y = rtfloor(R,k);
100         s = add(s,sum(m/k,x,y));
101     }
102     for(int l=2;l<=m;l++) if(m%l==0&&mu[l])
103     {
104         int t = 0;
105         for(int k=1;k*l<=m;k++) if(m%(k*l)==0)
106         {
107             int _l = max((int)ceil(pow(2,m/(k*l)/(db)D)),rtceil(L,k*l));
108             int _r = rtfloor(R,k*l);
109             t = add(t,sum(m/k*l,_l,_r));
110         }
111         s = add(s,mul(t,mu[l]));
112     }
113     return s;
114 }
115  
116 int work()
117 {
118     int s = 0;
119     pre();
120     for(lint m=D,p=2;p<=R;m+=D,p<<=1)
121         s = add(s,mul(c[m/D],calcg(m)));
122     return s;
123 }
124  
125 int main()
126 {
127     scanf("%d%d%d%d",&n,&D,&L,&R);
128     printf("%d\n",work());
129     return 0;
130 }
View Code

 

posted @ 2018-03-10 19:29  Cmd2001  阅读(197)  评论(0编辑  收藏  举报