zoukankan      html  css  js  c++  java
  • 北京集训: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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",work());
    129     return 0;
    130 }
    View Code
  • 相关阅读:
    程序Dog的大梦想
    图的存储结构
    c语言:函数的递归调用
    c语言:自增自减运算符的操作详解
    Shell 传递参数
    Shell 概述、截取字符操作等
    Python Falling back to the 'python' engine because the 'c' engine does not support regex separators
    Python IOError: [Errno 22] invalid mode ('r') 解决方法
    正则表达式 基础语法
    Hive 常用函数
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8541607.html
Copyright © 2011-2022 走看看