北京集训: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

 

转载于:https://www.cnblogs.com/Cmd2001/p/8541607.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/428013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rs232串口驱动_电脑主板RS232串口硬件设计

更多硬件设计培训视频&#xff0c; 欢迎加入微信公众号“陈苍硬件设计”RS232属于一种电平标准&#xff0c;采用UART异步通信串行数据总线协议。工业电平标准RS422和RS485同样采用UART协议。具体uart的协议格式和RS232电平标准大家可回顾下《低速接口视频》。我们这里主要讲解R…

vue编写to-do list源码

前端重于积累&#xff0c;下次使用不迷路。 纯vue代码 话不多说,直接上效果图: 源码附上: <template><div class"bgBody"><!-- 卡片--><el-row :gutter"12" ><el-col :span"8" ><el-card shadow"hov…

vue积累——另一种走马灯

效果图: vue源码: <template><el-carousel :interval"1500" type"card" height"400px" ><el-carousel-item v-for"item in imgList" :key"item.id"><img :src"item.idView" class"im…

假设检验背后的逻辑

内容转自知乎相关问题答案&#xff0c;写的很清晰。 1. 概述逻辑&#xff1a; 全称命题只能被否证而不能被证明。这个道理很简单&#xff0c;个案当然不足以证明一个全称命题&#xff0c;但是却可以否定全称命题。 研究时&#xff0c;我们当然不希望否证自己的研究假设&#xf…

Arduino上U8g2库自制中文库

U8g2最新版的本身自带中文库&#xff0c;之所以需要自制&#xff0c;是为了减小内存&#xff1b; 文章最后会标一下u8g2自带的中文库不过有些板子不能用gb2312等大字体&#xff1b; 字体库需要的是需要的是下面的这种编码&#xff0c;而实现这种编码&#xff0c;就需要map文件…

数据库创建(利用写好的数据库表生成创建表的sql语句+利用生成的数据库创建表加同步数据sql)

一.利用写好的数据库表生成创建表的sql语句 1.简单创建一个数据库&#xff0c;并建一个表&#xff0c;并编辑数据。 a.建库 b.建表 c.编辑表&#xff0c;保存时输入表名 d.刷新一下&#xff0c;出来了 e.转存导出sql文件。 二.利用生成的数据库创建表加同步数据sql。…

字符串之字符判断以及字母的大小写转换

char c //给定字符c 1.isalpha© //判断是否是字母 2.isdigit© //判断是否是数字 3.islower© //判断是否是小写字母 4.isupper© //判断是否是大写字母 5.tolower© //转变成小写字母 6.touper© //转变成代写字母 至于说应用&#xff0c;看代码悟吧…

symfony api 错误响应_Postman for Mac(API管理开发软件)

Postman for Mac是一款可在Mac端运行的API管理开发软件&#xff0c;postman 下载 mac不仅可以调试简单的css、html、脚本等简单的网页基本信息&#xff0c;它还可以发送几乎所有类型的HTTP请求&#xff0c;用户可以利用Chrome插件的形式把各种模拟用户HTTP请求的数据发送到服务…

前端学习

学习整理了web缓存的一些策略&#xff0c;如有不正确的地方&#xff0c;欢迎指正。 浏览器端的缓存规则 对于浏览器端的缓存来讲&#xff0c;这些规则是在HTTP协议头和HTML页面的Meta标签中定义的。他们分别从新鲜度和校验值两个维度来规定浏览器是否可以直接使用缓存中的副本&…

string的反转输出以及char型字符串的反转输出

string str; //string型变量str char str1[]; //char型变量str string的反转输出: reverse(str.begin(),str.end()) char型的反转输出: strrev(str1); 实际应用看参考代码: #include<iostream> #include<bits/stdc.h> using namespace std; int main() {string s…

数据流图怎么画_概率图模型怎么画?5个步骤完成专业模型图

概率图模型是什么呢&#xff1f;概率图模型是用图形模式来表示各个变量概率相关关系以及与模型有关的变量的联合概率分布的一类模型。概率图理论可分为概率图模型表示理论、概率图模型推理理论和概率图模型学习理论三部分。概率图模型一般包括贝叶斯网络、马尔可夫网络和隐马尔…

res.status === 200含义

200本身就是http请求成功的响应值

process启动jar包判断成功_恒一广告助力2020年壹基金温暖包安康发放启动仪式成功举办...

有爱的冬天不会冷11月28日上午&#xff0c;由共青团安康市委、安康市教育体育局、安康市民政局、安康市关心下一代组委会、安康广播电视台、安康义工联合会主办的“壹家人温暖安康共青团助力脱贫攻坚暖冬行动”暨2020年壹基金温暖包安康发放启动仪式在安康市金州体育场成功举办…

pat(基本编程题集)6-2 多项式求值 (15 分)

这道题感觉有点狗&#xff0c;不难&#xff0c;但是第一次做的时候&#xff0c;运行超时错误让我很不解&#xff0c;一共才10个数大的数组&#xff0c;最坏情况也不过是10*10的时间复杂度O&#xff08;1&#xff09;。 但是限制就是辣么严&#xff0c;这个单层循环的优化有些类…

Zabbix Server设置主机监控

转载于:https://www.cnblogs.com/momenglin/p/8557447.html

C语言之double实数的自动四舍五入取整

之前学习C语言的时候一直没有注意到原来double类型的数据在C里通过取不同的小数位数&#xff0c;输出能够实现四舍六入。 指正: double型数据可以实现0到4的舍操作以及6到9的入操作&#xff0c; 在真值为5的时候&#xff0c;舍入并不确定。 这里通过一个案例&#xff0c;一看…

mysql修改字段默认值_MySQL增删改查操作

增删改查操作查询表中的所有的记录&#xff1a;select from 表名(xs)创建数据库&#xff1a;create database if not exists xsgl;8.2创建表&#xff1a;cerate table if not exists&#xff08;判断是否存在&#xff09; 表名&#xff08;xsb&#xff09;8.3删除&#xff1a;d…

三羊献瑞(暴力破解)

package 计蒜客;public class 三羊献瑞 {/*** param args*/public static void main(String[] args) {// TODO Auto-generated method stubfor(int i5000;i<9876;i){for(int j1023;j<9876;j){int kij;int ai/1000;int b(i/100)%10;int c(i/10)%10;int di%10;int ej/1000;…

回来来看初学C语言的一些有趣的图形的输出

现在再来看那些当初觉得困难的东西&#xff0c;经常都会一笑而过。 图1: a.源码: #include<iostream> using namespace std; int main() {int n;cin>>n;for(int i1;i<n;i){for(int j1;j<n-i;j){cout<<" ";}for(int k1;k<n;k){cout<&l…

视图添加字段_使用ExploreByTouchHelper辅助类为自定义视图添加虚拟视图

在安卓开发过程中&#xff0c;为了视觉和功能的需要开发者经常会使用自定义视图大多数的自定义视图是组合现有的控件来完成特定的功能但是&#xff0c;有一种自定义视图是通过画笔在画布上画出自定义的子视图的&#xff0c;例如日期控件&#xff0c;颜色选择面板等由于自定义视…