zoukankan      html  css  js  c++  java
  • [考试反思]0506省选模拟89:无事

    难得没挂分。。。通过卡常水了个$rk1$

    $T1$是博弈论,打个$SG$表然后倒没啥扩展就是要写个高精。

    $T2$啥都不会暴拆式子交暴力。最开始$OJ$又波动了干掉我$5$分重测就回来了。

    $T3$打的$35$暴力然后看着只有$5 imes 10^4$的数据范围蠢蠢欲动于是大力卡常$n^2$多拿了$10$分。

    倒也没啥水平就是纯粹想不想写的问题吧。。。谁还不会卡常啊。。。

    T1:石子

    大意:$m$堆石子,每次可以选一堆,假如剩下$x$个那么可以拿走$d$个要求$d eq x,d|x$。不能拿的人输。问每堆石子最多$n$个则有多少种先手必胜局面。$nle 10^{10000},m le 10^{18}$

    博弈论。每堆互不影响。所以考虑每一堆的$SG$异或起来就行。

    考虑一堆,打表发现对于一个数$x=a imes 2^b$($a$是奇数)。则$SG(x)=b$

    对于$x=1$显然。

    对于一个奇数,它的所有决策都是拿走奇数个,剩余状态是偶数,$SG>0$。$mex$之后可知$SG(x)$当$x$为奇数时为零。

    对于一个偶数,它可能的决策是拿走$2^0,2^1,2^2,...,2^b$。(可能最后一项是非法的,当$a=1$的时候)

    前面乘上一个奇系数没影响。这样所到达的状态都恰好是$2^0,2^1,2^2...2^b$的倍数。

    所对应的$SG$分别是$0,1,2,...,b-1,?$。其中$?$是一个$>b$的数。

    所以$SG=b$。归纳得证。

    所以同时也就知道了$SG$是$log_2n$级别的。大约是$30000$

    然后我们需要知道每种$SG$有多少个数。也就是:有多少奇数,有多少$2$的倍数而不是$4$的倍数。。。说白了就是$lowbit$

    只需要每次$a=lceil frac{n}{2} ceil$。然后$n leftarrow frac{n}{2}$

    这里需要高精除低精是$log_2^2n$的有点大。但是只要顺手写个十亿进制压位常数就除$9$了就没问题了。

    然后剩下的就是$30000$个$SG$。讲$m$个这玩意异或起来结果不是$0$的方案数。$FWT$板子。

    叠个快速幂。总复杂度$O(frac{log^2_2n}{9} + log_2nlog(log_2n) + log_2nlog m)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 998244353
     4 int mo(int x){return x>=mod?x-mod:x;}
     5 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     6 #define S 1<<20
     7 int lg,SG[S],ans[S],Ans,n[S],bn,rev[S],len; long long m; char N[S];
     8 void FWT(int*a,int op=1){
     9     for(int i=0;i<len;++i)if(rev[i]>i)swap(a[i],a[rev[i]]);
    10     for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=i<<1)
    11         for(int k=j,x,y;k<j+i;++k)
    12             x=a[k],y=a[k+i],a[k]=mo(x+y),a[k+i]=mo(x+mod-y);
    13     if(op==-1)for(int iv=qp(len,mod-2),i=0;i<len;++i)a[i]=1ll*a[i]*iv%mod;
    14 }
    15 int main(){
    16     scanf("%s%lld",N,&m); len=strlen(N); reverse(N,N+len);
    17     for(int j=len-1;~j;--j)n[j/9+1]=n[j/9+1]*10+N[j]-48;
    18     len=(len-1)/9+1;
    19     for(lg=0;len;++lg){
    20         SG[lg]=n[1]&1; int x=0;
    21         for(int j=len;j;--j)n[j-1]+=(n[j]&1)*1000000000,n[j]>>=1,x=(x*1000000000ll+n[j])%mod;
    22         SG[lg]+=x; while(len&&!n[len])len--;
    23     }
    24     ans[0]=len=1;
    25     while(len<=lg)len<<=1;
    26     for(int i=1;i<len;++i)rev[i]=rev[i>>1]>>1|(i&1?len>>1:0);
    27     FWT(ans);FWT(SG);
    28     for(;m;m>>=1){
    29         if(m&1)for(int i=0;i<len;++i)ans[i]=1ll*ans[i]*SG[i]%mod;
    30         for(int i=0;i<len;++i)SG[i]=1ll*SG[i]*SG[i]%mod;
    31     }FWT(ans,-1);
    32     for(int i=1;i<len;++i)Ans=mo(Ans+ans[i]);
    33     printf("%d
    ",Ans);
    34 }
    View Code

    T2:奥术

    大意:数串。支持复制一段区间到另一段,询问一个子串,它的所有子串的值的和。$n,Q le 10^5$

    发现答案是关于$1,l,10^r,l imes 10^r$的一次项式的和。线段树维护暴力修改。

    然后赋值操作可以可持久化平衡树。需要定期重构。写个毛线。

    然而貌似不是完全不能理解。贴个$std$方便以后回来看。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cctype>
      4 #include<algorithm>
      5 #define rep(i,s,t) for(int i=s;i<=t;i++)
      6 #define dwn(i,s,t) for(int i=s;i>=t;i--)
      7 using namespace std;
      8 inline int read(){
      9     int x=0,f=1;char c=getchar();
     10     for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
     11     for(;isdigit(c);c=getchar()) x=x*10+c-'0';
     12     return x*f;
     13 }
     14 typedef long long ll;
     15 const int maxn=160010,mod=998244353,maxnode=1500010;
     16 int ToT,ls[maxnode],siz[maxnode],rs[maxnode];
     17 int qpow(int n,int m){
     18     int ans=1;
     19     for(;m;m>>=1,n=(ll)n*n%mod) if(m&1) ans=(ll)ans*n%mod;
     20     return ans;
     21 }
     22 int n,m,b,f[maxn],pw[maxn];
     23 char s[maxn];
     24 struct Node {
     25     int axb,ax,xb,x,l;
     26     Node(int v=0){l=1;x=ax=v;axb=xb=(ll)b*v%mod;}
     27     Node operator+(Node b){
     28         if(!b.l) return *this;
     29         if(!l) return b;
     30         Node c(0);
     31         c.l=l+b.l;
     32         c.x=(x+b.x)%mod;
     33         c.ax=((ax+b.ax)%mod+(ll)l*b.x%mod)%mod;
     34         c.xb=(b.xb+(ll)xb*pw[b.l]%mod)%mod;
     35         c.axb=(ll)axb*pw[b.l]%mod;
     36         (c.axb+=((ll)l*b.xb%mod+b.axb)%mod)%=mod;
     37         return c;
     38     }
     39     int ans(){
     40         int res=(axb-ax+mod)%mod;
     41         res=(ll)res*qpow(((ll)l*(l+1)/2)%mod*(b-1)%mod,mod-2)%mod;
     42         return res;
     43     }
     44 }sumv[maxnode];
     45 int val[maxnode];
     46 void copy(int&y,int x){
     47     ls[y]=ls[x];rs[y]=rs[x];siz[y]=siz[x];
     48     sumv[y]=sumv[x];val[y]=val[x];
     49 }
     50 void maintain(int x){
     51     siz[x]=siz[ls[x]]+siz[rs[x]]+1;
     52     sumv[x]=sumv[ls[x]]+(Node(val[x]));
     53     sumv[x]=sumv[x]+sumv[rs[x]];
     54 }
     55 void split(int o,int k,int&left,int&right){
     56     if(!k) {left=0,right=o;return;}
     57     if(k==siz[o]) {left=o,right=0;return;}
     58     int z=++ToT;copy(z,o);
     59     if(siz[ls[z]]>=k) {
     60         right=z;split(ls[z],k,left,ls[right]);
     61         maintain(right);
     62     }else{
     63         left=z;split(rs[z],k-siz[ls[z]]-1,rs[left],right);
     64         maintain(left);
     65     }
     66 }
     67 int Rand(){return (rand()<<15)|rand();}
     68 int merge(int x,int y){
     69     if(!x) return y;
     70     if(!y) return x;
     71     int z=++ToT;
     72     if(Rand()%(siz[x]+siz[y])<=siz[x]){
     73         copy(z,x);rs[z]=merge(rs[z],y);
     74         maintain(z);
     75         return z;
     76     }else{
     77         copy(z,y);ls[z]=merge(x,ls[z]);
     78         maintain(z);
     79         return z;
     80     }
     81 }
     82 void build(int&o,int l,int r){
     83     o=0;if(l>r) return;
     84     int mid=l+r>>1;o=++ToT;val[o]=s[mid]-'0';
     85     build(ls[o],l,mid-1);build(rs[o],mid+1,r);
     86     maintain(o);
     87 }
     88 int cnt;
     89 void print(int o){
     90     if(!o) return;
     91     print(ls[o]);
     92     s[++cnt]=val[o]+'0';
     93     print(rs[o]);
     94 }
     95 int main() {
     96     n=read();m=read();b=10;sumv[0].l=0;
     97     f[1]=1;pw[1]=b;pw[0]=1;
     98     rep(i,1,n+1) f[i+1]=((ll)f[i]*b%mod+1)%mod,pw[i+1]=(ll)pw[i]*b%mod;
     99     scanf("%s",s+1);
    100     int root,o,left,mid,right,tmp;
    101     build(root,1,n);
    102     while(m--) {
    103         int t=read(),l=read(),r=read();
    104         if(t==1) {
    105             split(root,l-1,left,o);
    106             split(o,r-l+1,mid,right);
    107             printf("%d
    ",sumv[mid].ans());
    108         }else{
    109             int x=read()+1;swap(l,r);
    110             split(root,l-1,left,o);
    111             split(o,x,mid,right);
    112             split(root,r-1,left,o);
    113             split(o,x,tmp,right);
    114             root=merge(left,mid);
    115             root=merge(root,right);
    116         }
    117         if(m%10000==0) {
    118             cnt=ToT=0;
    119             print(root);
    120             build(root,1,n);
    121         }
    122     }
    123 }
    View Code

    T3:排列

    大意:求所有满足最长上升/下降子串长度$le 2$的长度介于$[L,R]$之间的排列个数。$R le 10^6$

    首先这差不多是个原题。可以用同样的方法做。只不过最后统计答案的时候稍微改变一下。

    当时计数的是对于某个特定长度。换成一个区间后,发现是卷积形式。。。$O(nlogn)$

    题解做法是,首先设$f_n$表示长度为$n$的满足条件的排列个数。

    发现$W,M$形排列是相对的只要计数其中一种最后再乘$2$即可。(特殊考虑$n=1$)

    我们假如只计数$W$形。枚举数字$n$所在的位置,得到$f_n= sumlimits_{i=1}^{frac{n}{2}} inom{n-1}{2i-2} f_{2i-2} f_{n-(2i-1)}$

    同理枚举数字$1$的位置,得到$f_n=sumlimits_{i=1}^{frac{n}{2}} inom{n-1}{2i-1} f_{2i-1} f_{n-2i}$

    二式相加得到$f_n =sumlimits_{i=1}^{n} inom{n-1}{i-1} f_{i-1} f_{n-i}$

    拆开组合数得到$frac{2f_n}{(n-1)!} = sumlimits_{i=0}^{n-1} frac{f_i}{i!} frac{f_{n-i-1}}{(n-i-1)!}$

    很像指数型生成函数。但是左边错位了且还有系数。错位可以用导数处理,故得到$2F'=F^2+1$

    $frac{F'}{F^2+1}=frac{1}{2}$

    我们有$tan'(x)=(frac{sin}{con})'(x) = frac{sin^2(x)+cos^2(x)}{cos^2(x)}=1+tan^2(x)$

    然后就有设$arctan'(y)=frac{1}{1+y^2}$。考虑$y=tan(x)$,定义域仍然是$R$。

    所以其实也就是$x$关于$tan(x)$的导数。

    所以也就是$tan(x)$关于$x$的导数的倒数。

    所以也就是$frac{1}{1+tan^2(x)}$。代回得到$frac{1}{1+y^2}$

    所以发现原式就是$arctan'(F(x))$的形式。(复合函数求导)

    所以我们得到$arctan'(F(x))=frac{1}{2}$。

    所以有$arctan(F(x))=frac{1}{2}x+c$(根据导数还原原函数,然而还原时可能会多出来一个常数,是在求导时消失的常数项)

    所以$F(x)=tan(frac{1}{2}x+c)$

    显然有$F(0)=1$。带入得知$c=frac{pi}{4}$

    $tan(frac{1}{2}x+frac{pi}{4})$

    $ = frac{sin(frac{1}{2}x+frac{pi}{4})}{cos(frac{1}{2}x+frac{pi}{4})}$

    $ = frac{sin(frac{1}{2}x)+cos(frac{1}{2}x)}{cos(frac{1}{2}x)-sin(frac{1}{2}x)}$

    $ = frac{sin^2(frac{1}{2}x)+cos^2(frac{1}{2}x)+2sin(frac{1}{2}x)cos(frac{1}{2}x)}{cos^2(frac{1}{2}x)-sin^2(frac{1}{2}x)}$

    $=frac{1+sin(x)}{cos(x)}$

    然后只需要级数求和。。。

    $sin(x)=sum (-1)^{i-1} frac{x^{2i-1}}{(2i-1)!}$

    $cos(x)=sum (-1)^i frac{x^{2i}}{(2i)!}$

    然后多项式求逆就没了。$O(nlogn)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 998244353
     4 #define S 1<<21
     5 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     6 int mo(int x){return x>=mod?x-mod:x;}
     7 int rev[S],a[S],r[S],L,R,len,X[S],fac[S],inv[S],ans;
     8 void NTT(int*a,int op=1){
     9     for(int i=0;i<len;++i)if(rev[i]>i)swap(a[i],a[rev[i]]);
    10     for(int i=1;i<len;i<<=1)for(int j=0,w=qp(3,(mod-1)/i/2*op+mod-1);j<len;j+=i<<1)
    11         for(int k=j,t=1,x,y;k<j+i;++k,t=1ll*t*w%mod)
    12             x=a[k],y=1ll*a[k+i]*t%mod,a[k]=mo(x+y),a[k+i]=mo(mod+x-y);
    13     if(op==-1)for(int i=0,iv=qp(len,mod-2);i<len;++i)a[i]=1ll*a[i]*iv%mod;
    14 }
    15 void sat(int x){
    16     len=1;while(len<=x)len<<=1;
    17     for(int i=0;i<len;++i)rev[i]=rev[i>>1]>>1|(i&1?len>>1:0);
    18 }
    19 void Inv(int*a,int n){
    20     static int R[S];
    21     if(n==1){r[0]=qp(a[0],mod-2);return;}
    22     Inv(a,n+1>>1); sat(n<<1);
    23     for(int i=0;i<len;++i)R[i]=i<n?a[i]:0;
    24     NTT(R);NTT(r); for(int i=0;i<len;++i)r[i]=(r[i]+r[i]-R[i]*1ll*r[i]%mod*r[i]%mod+mod)%mod;
    25     NTT(r,-1); for(int i=n;i<len;++i)r[i]=0;
    26 }
    27 int main(){
    28     scanf("%d%d",&L,&R);
    29     for(int i=fac[0]=1;i<=R;++i)fac[i]=fac[i-1]*1ll*i%mod;
    30     inv[R]=qp(fac[R],mod-2);
    31     for(int i=R-1;~i;--i)inv[i]=inv[i+1]*(i+1ll)%mod;
    32     for(int i=0;i<=R;i+=2)a[i]=i>>1&1?mod-inv[i]:inv[i];
    33     Inv(a,R+1); sat(R+R);
    34     for(int i=0;i<=R;++i)a[i]=0;
    35     for(int i=a[0]=1;i<=R;i+=2)a[i]=i>>1&1?mod-inv[i]:inv[i];
    36     NTT(r);NTT(a); for(int i=0;i<len;++i)a[i]=a[i]*1ll*r[i]%mod; NTT(a,-1);
    37     for(int i=L;i<=R;++i)ans=(ans+1ll*fac[i]*a[i])%mod;
    38     printf("%d
    ",ans*2%mod-(L==1));
    39 }
    View Code
  • 相关阅读:
    11-8 Eureka Server整合SpringSecurity解决安全问题
    11-7 Eureka Server安全问题介绍
    11-6 CORS跨域资源共享解决
    11-5 JWT验证演示
    11-4 JWT验证开发演示
    11-3 JWT颁发流程讲解
    11-2 JWT介绍
    11-1 服务安全章节介绍
    10-15 Zuul知识点梳理
    10-14 Zuul与Meetingfilm整合
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12838083.html
Copyright © 2011-2022 走看看