• 北京集训:20180318


    果然我还是太菜了......

    T1:


    先分解成标准形式,然后每个质因数必须有最高次,然后状压DP?
    发现并不可做......
    然后写了10分的大力背包走了......
    正解是容斥。


    然而他的公式挂了......
    大概意思就是枚举我们有几个没有到最高次,然后用高维前缀和(积)进行DP。
    关于高维前缀和可以看我以前的博客......
    为什么考场没想起来......
    考场10分代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 //#include<iostream>
     4 //#define debug cout
     5 //using namespace std;
     6 typedef long long int lli;
     7 const int maxn=5e2+1e1,maxk=22;
     8 const int mod=232792561;
     9 
    10 lli f[2][maxn][maxk];
    11 int n,k;
    12 
    13 inline int gcd(int x,int y) {
    14     register int t;
    15     while( t = x % y )
    16         x = y , y = t;
    17     return y;
    18 }
    19 inline int lcm(int x,int y) {
    20     if( ! ( x && y ) ) return x | y;
    21     return x / gcd(x,y) * y;
    22 }
    23 inline void trans(lli dst[maxn][maxk],const lli sou[maxn][maxk],int now) {
    24     for(int i=0;i<=n;i++) {
    25         const int tar = lcm(i,now);
    26         if( tar > n ) continue;
    27         for(int j=0;j<k;j++) ( dst[tar][(j+now)%k] += sou[i][j] ) %= mod;
    28     }
    29     for(int i=0;i<=n;i++)
    30         for(int j=0;j<k;j++)
    31             ( dst[i][j] += sou[i][j] ) %= mod;
    32 }
    33 
    34 int main() {
    35     static int T,cur;
    36     scanf("%d",&T);
    37     while(T--) {
    38         memset(f,0,sizeof(f)) , cur = 0;
    39         f[cur][0][0] = 1;
    40         scanf("%d%d",&n,&k);
    41         for(int i=1;i<=n;i++) {
    42             cur ^= 1;
    43             memset(f[cur],0,sizeof(f[1]));
    44             trans(f[cur],f[cur^1],i);
    45         }
    46         printf("%lld
    ",f[cur][n][0]);
    47     }
    48     return 0;
    49 }
    View Code

    正解代码:

      1 //#include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 //#include<algorithm>
      5 //#define debug cout
      6 typedef long long int lli;
      7 //using namespace std;
      8 const int maxl=2e5+1e2,maxd=2e1+1e1,maxp=7e1+1e1;
      9 const int mod=232792561;
     10 
     11 int k;
     12 lli wpows[maxd];
     13 
     14 inline lli fastpow(lli base,int tim) {
     15     lli ret = 1;
     16     while( tim ) {
     17         if( tim & 1 ) ret = ret * base % mod;
     18         if( tim >>= 1 ) base = base * base % mod;
     19     }
     20     return ret;
     21 }
     22 
     23 struct Poly {
     24     lli dat[maxd];
     25     Poly() {
     26         memset(dat,0,sizeof(dat));
     27     }
     28     inline void fill(int x) { // get point value expression , only p ^ x and p ^ 0 is 1 .
     29         for(int i=0;i<k;i++)
     30             dat[i] = ( wpows[x*i%k] + 1 ) % mod;
     31     }
     32     friend Poly operator + (const Poly &a,const Poly &b) {
     33         Poly ret;
     34         for(int i=0;i<k;i++) ret.dat[i] = ( a.dat[i] + b.dat[i] ) % mod;
     35         return ret;
     36     }
     37     friend Poly operator - (const Poly &a,const Poly &b) {
     38         Poly ret;
     39         for(int i=0;i<k;i++) ret.dat[i] = ( a.dat[i] - b.dat[i] + mod ) % mod;
     40         return ret;
     41     }
     42     friend Poly operator * (const Poly &a,const Poly &b) {
     43         Poly ret;
     44         for(int i=0;i<k;i++) ret.dat[i] = a.dat[i] * b.dat[i] % mod;
     45         return ret;
     46     }
     47     inline lli calc() {
     48         lli ret = 0;
     49         for(int i=0;i<k;i++) ( ret += dat[i] ) %= mod;
     50         ret = ret * fastpow(k,mod-2) % mod;
     51         return ret;
     52     }
     53 }f[maxl];
     54 
     55 lli dvs[maxd],dvspows[maxd][maxp];
     56 int tim[maxd],facs[maxd];
     57 int cnt,full;
     58 
     59 inline void prew() {
     60     const lli w = fastpow(71,mod/k);
     61     *wpows = 1;
     62     for(int i=1;i<k;i++) wpows[i] = wpows[i-1] * w % mod;
     63 }
     64 inline void cut(lli x) {
     65     for(int i=2;i<=100;i++)
     66         if( ! ( x % i ) ) {
     67             dvs[++cnt] = i , dvspows[cnt][0] = 1;
     68             while( ! ( x % i ) ) {
     69                 ++tim[cnt] ,
     70                 dvspows[cnt][tim[cnt]] = dvspows[cnt][tim[cnt]-1] * i ,
     71                 x /= i;
     72             }
     73         }
     74 }
     75 inline void getfac() {
     76     *facs = 1;
     77     for(int i=1;i<=cnt;i++) facs[i] = facs[i-1] * ( tim[i] + 1 );
     78 }
     79 inline lli getnum(int id) { // access as high-dimension array .
     80     lli ret = 1;
     81     for(int i=1;i<=cnt;i++) ret *= dvspows[i][id%facs[i]/facs[i-1]];
     82     return ret;
     83 }
     84 inline void dp() {
     85     for(int j=1;j<=cnt;j++)
     86         for(int i=0;i<full;i++)
     87             if( i % facs[j] / facs[j-1] )
     88                 f[i] = f[i] * f[i-facs[j-1]];
     89 }
     90 inline Poly getans() {
     91     Poly ret;
     92     for(int sta=0;sta<(1<<cnt);sta++) {
     93         int sg = 1 , now = full - 1;
     94         for(int i=1;i<=cnt;i++) if( sta & ( 1 << ( i - 1 ) ) ) {
     95             sg *= -1 , now -= facs[i-1];
     96         }
     97         if( sg == 1 ) ret = ret + f[now];
     98         else ret = ret - f[now];
     99     }
    100     return ret;
    101 }
    102 inline void init() {
    103     memset(tim,0,sizeof(tim)) , cnt = 0;
    104     memset(f,0,sizeof(f));
    105 }
    106 
    107 int main() {
    108     static int T;
    109     static lli n;
    110     scanf("%d",&T);
    111     while(T--) {
    112         scanf("%lld%d",&n,&k) , init() , prew();
    113         cut(n) , getfac() , full = facs[cnt];
    114         for(int i=0;i<full;i++) {
    115             lli now = getnum(i);
    116             f[i].fill(now%k);
    117         }
    118         dp();
    119         Poly ans = getans();
    120         printf("%lld
    ",ans.calc());
    121     }
    122     return 0;
    123 }
    View Code


    T2:


    显然是个反演+杜教筛......
    三个gcd很不好办啊,拆了他也不好做,不如留着,万一大力出奇迹了呢......


    前面是μ*id=φ,后面是x^2的前缀和,显然可以背过......
    话说考场如果背不过怎么办呢?显然他是一个k+1次多项式,然后我们可以拉格朗日插值......
    官方题解感觉推傻了......


    考场AC代码:

     1 //#include<iostream>
     2 #include<cstdio>
     3 //#include<cstring>
     4 //#include<algorithm>
     5 //#define debug cout
     6 typedef long long int lli;
     7 //using namespace std;
     8 const int maxn=1e6+1e2,lim=1e6;
     9 
    10 lli phi[maxn],mem[maxn],vis[maxn];
    11 int n,mod,inv;
    12 
    13 inline lli fastpow(lli base,int tim) {
    14     lli ret = 1;
    15     while( tim ) {
    16         if( tim & 1 ) ret = ret * base % mod;
    17         if( tim >>= 1 ) base = base * base % mod;
    18     }
    19     return ret;
    20 }
    21 
    22 inline void sieve() {
    23     static int vis[maxn],prime[maxn],cnt;
    24     phi[1] = 1;
    25     for(int i=2;i<=lim;i++) {
    26         if( !vis[i] ) prime[++cnt] = i , phi[i] = i - 1;
    27         for(int j=1;j<=cnt&&(lli)i*prime[j]<=lim;j++) {
    28             const int tar = i * prime[j];
    29             vis[tar] = 1; 
    30             if( i % prime[j] ) phi[tar] = phi[i] * ( prime[j] - 1 );
    31             else {
    32                 phi[tar] = phi[i] * prime[j];
    33                 break;
    34             }
    35         }
    36     }
    37     for(int i=1;i<=lim;i++) ( phi[i] += phi[i-1] ) %= mod;
    38 }
    39 
    40 inline lli sumphi(lli x) {
    41     if( x <= lim )
    42         return phi[x];
    43     lli mp = n / x;
    44     if( vis[mp] )
    45         return mem[mp];
    46     lli ret = ( (lli) x ) * ( x + 1 ) >> 1;
    47     for(lli i=2,j;i<=x;i=j+1) {
    48         j = x / ( x / i );
    49         ret -= ( j - i + 1 ) * sumphi( x / i );
    50     }
    51     vis[mp] = 1;
    52     return mem[mp] = ret;
    53 }
    54 
    55 inline lli sum(lli x) {
    56     return x * ( x + 1 ) % mod * ( ( 2 * x + 1 ) % mod ) % mod * inv % mod;
    57 }
    58 inline lli segphi(lli l,lli r) {
    59     return ( sumphi(r) - sumphi(l-1) + mod ) % mod;
    60 }
    61 inline lli calc(lli n) {
    62     lli ret = 0;
    63     for(lli i=1,j;i<=n;i=j+1) {
    64         j = n / ( n / i );
    65         ( ret += segphi(i,j) * sum( n / i ) % mod ) %= mod;
    66     }
    67     return ret;
    68 }
    69 
    70 int main() {
    71     scanf("%d%d",&n,&mod) , sieve();
    72     inv = fastpow(6,mod-2);
    73     printf("%lld
    ",calc(n));
    74     return 0;
    75 }
    View Code


    T3:


    字符串题,没时间了,写个20分暴力走了。
    woc暴力怎么又WA了?
    题解:


    考场零分暴力:

     1 //#include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 //#include<algorithm>
     5 #include<queue>
     6 //#define debug cout
     7 typedef long long int lli;
     8 //using namespace std;
     9 const int maxn=1e2+1e1,maxq=1e5+1e2;
    10 
    11 struct ACautomatic {
    12     int ch[maxn][26],fail[maxn],deg[maxn],sum[maxn],tim[maxn],root,cnt;
    13     ACautomatic() { root = ++cnt; }
    14     inline void insert(char* s,int li) {
    15         int now = root;
    16         for(int i=1;i<=li;i++) {
    17             const int t = s[i] - 'a';
    18             if( !ch[now][t] ) ch[now][t] = ++cnt;
    19             now = ch[now][t];
    20         }
    21         //debug<<"now = "<<now<<endl;
    22         ++sum[now];
    23     }
    24     inline void buildfail() {
    25         std::queue<int> q;
    26         for(int i=0;i<26;i++)
    27             if( !ch[root][i] ) ch[root][i] = i;
    28             else fail[ch[root][i]] = root , q.push(ch[root][i]);
    29         while( q.size() ) {
    30             const int pos = q.front(); q.pop();
    31             for(int i=0;i<26;i++)
    32                 if( !ch[pos][i] ) ch[pos][i] = ch[fail[pos]][i];
    33                 else fail[ch[pos][i]] = ch[fail[pos]][i] , q.push(ch[pos][i]);
    34         }
    35     }
    36     inline void pir(char* s,int li) {
    37         int now = root;
    38         for(int i=0;i<li;i++) {
    39             const int t = s[i] - 'a';
    40             //debug<<"now = "<<now<<endl;
    41             now = ch[now][t] , ++tim[now];
    42         }
    43     }
    44     inline lli calc() {
    45         lli ret = 0;
    46         std::queue<int> q;
    47         for(int i=1;i<=cnt;i++) if( fail[i] ) ++deg[fail[i]];
    48         for(int i=1;i<=cnt;i++) if( !deg[i] ) q.push(i);
    49         while( q.size() ) {
    50             const int pos = q.front(); q.pop();
    51             if( pos == root ) continue;
    52             ret += (lli) tim[pos] * sum[pos];
    53             tim[fail[pos]] += tim[pos];
    54             if( !--deg[fail[pos]] ) q.push(fail[pos]);
    55         }
    56         return ret;
    57     }
    58     inline void rtq() {
    59         memset(deg,0,sizeof(deg)) , memset(tim,0,sizeof(tim));
    60     }
    61 }AC;
    62 
    63 char in[maxq],tp[maxq];
    64 
    65 int main() {
    66     static int n,q,li;
    67     scanf("%d%d",&n,&q);
    68     for(int i=1;i<=n;i++) {
    69         scanf("%s",tp+1) , li = strlen(tp+1);
    70         AC.insert(tp,li);
    71     }
    72     AC.buildfail();
    73     scanf("%s",in+1);
    74     for(int i=1,o,l,r;i<=q;i++) {
    75         scanf("%d%d%d",&o,&l,&r);
    76         if( o == 2 ) {
    77             AC.rtq();
    78             AC.pir(in+l,r-l+1);
    79             printf("%lld
    ",AC.calc());
    80         } else {
    81             scanf("%s",tp) , li = strlen(tp);
    82             for(int j=0;j<r-l+1;j++)
    83                 in[l+j] = tp[j%li];
    84         }
    85     }
    86     return 0;
    87 }
    View Code

    标程:

      1 #include<bits/stdc++.h>
      2 #define ALPHA 27
      3 #define N 55
      4 #define M 100005
      5 #define pii pair<int,int>
      6 #define mp(x,y) make_pair(x,y)
      7 #define fr first
      8 #define se second 
      9 using namespace std;
     10 namespace AC{
     11     int ne[M][ALPHA],fail[M],val[M],cnt,root;//0~cnt-1
     12     void insert(int &k,char *s,int len){
     13         if(k==0) k=++cnt;
     14         if(len!=0) insert(ne[k][s[0]-'a'],s+1,len-1);
     15         else val[k]++;
     16     }
     17     void buildAC(){
     18         fail[root]=root;queue<int> q;
     19         for(int i=0;i<26;i++)
     20             if(ne[root][i]==0) ne[root][i]=root;
     21             else fail[ne[root][i]]=root,q.push(ne[root][i]);
     22         while(!q.empty()){
     23             int u=q.front();q.pop();
     24             for(int i=0;i<26;i++){
     25                 int &v=ne[u][i];
     26                 if(v==0) v=ne[fail[u]][i];
     27                 else fail[v]=ne[fail[u]][i],q.push(v),val[v]+=val[fail[v]];
     28             }
     29         }
     30     }
     31 }
     32  
     33 struct msg{
     34     int st[N],ans[N];
     35     pii query(pii x){
     36         return mp(st[x.fr],x.se+ans[x.fr]);
     37     }
     38     void merge(const msg &b){
     39         for(int i=0;i<AC::cnt;i++) ans[i]+=b.ans[st[i]],st[i]=b.st[st[i]];
     40     }
     41     void ini(){
     42         for(int i=0;i<AC::cnt;i++) st[i]=i,ans[i]=0;
     43     }
     44     void inital(char ch){
     45         for(int i=0;i<AC::cnt;i++) st[i]=AC::ne[i+1][ch-'a']-1,ans[i]=AC::val[st[i]+1];
     46     }
     47 };
     48 msg ne[M*19];
     49 #define gid(pos,pw) ((pos)*18+(pw))
     50 char str[M];int len,lenth[M],li[M],ri[M],idcnt;
     51 void prework(int l,int r,int d){
     52     int mlen=(r-l+1);
     53     for(int i=l;i<=r;i++) ne[gid(i,0)].inital(str[i]);
     54     for(int i=1;(1<<i)<=d;i++)
     55         for(int j=l;j<=r;j++)
     56             ne[gid(j,i)]=ne[gid(j,i-1)],ne[gid(j,i)].merge(ne[gid((j-l+(1<<(i-1)))%mlen+l,i-1)]);
     57 }
     58  
     59 namespace SGT{
     60     struct xds{
     61         int pw;
     62         msg x;
     63         int tagid,pos;
     64     }a[(1<<18)+3];int cnt;
     65     inline void addmark(int k,int id,int pos){
     66         a[k].x=ne[gid(li[id]+pos,a[k].pw)];
     67         a[k].tagid=id;a[k].pos=pos;
     68     }
     69     inline void pushdown(int k){
     70         if(a[k].tagid==0||a[k].pw==0) return;
     71         addmark(k<<1,a[k].tagid,a[k].pos);
     72         int npos=(a[k].pos+(1<<(a[k].pw-1)))%lenth[a[k].tagid];
     73         addmark(k<<1|1,a[k].tagid,npos);
     74         a[k].tagid=0;a[k].pos=0;
     75     }
     76     inline void update(int k){
     77         a[k].x=a[k<<1].x;
     78         a[k].x.merge(a[k<<1|1].x);
     79     }
     80     void build(int k,int l,int r,char *s,int pw){
     81         a[k].pw=pw;
     82         if(l==r){
     83             a[k].x.inital(s[l]);return;
     84         }else{
     85             int mid=(l+r)>>1;
     86             build(k<<1,l,mid,s,pw-1);
     87             build(k<<1|1,mid+1,r,s,pw-1);
     88             update(k);
     89         }
     90     }
     91     pii query(int k,int l,int r,pii input,int nl,int nr){
     92         if(nl==l&&nr==r) return a[k].x.query(input);
     93         pushdown(k);
     94         int mid=(nl+nr)>>1;
     95         if(l>mid) return query(k<<1|1,l,r,input,mid+1,nr);
     96         else if(r<=mid) return query(k<<1,l,r,input,nl,mid);
     97         return query(k<<1|1,mid+1,r,query(k<<1,l,mid,input,nl,mid),mid+1,nr);
     98     }
     99     void modify(int k,int l,int r,int id,int st,int nl,int nr){
    100         if(nl==l&&nr==r){
    101             addmark(k,id,st);
    102         }else{
    103             pushdown(k);
    104             int mid=(nl+nr)>>1;
    105             if(l>mid) modify(k<<1|1,l,r,id,st,mid+1,nr);
    106             else if(r<=mid) modify(k<<1,l,r,id,st,nl,mid);
    107             else modify(k<<1,l,mid,id,st,nl,mid),modify(k<<1|1,mid+1,r,id,(st+mid-l+1)%lenth[id],mid+1,nr);
    108             update(k);
    109         }
    110     }
    111 }
    112  
    113 char s[(1<<18)+3],Ti[N];
    114 int n,m,q,pwlen;
    115 void readin(){
    116     //cerr<<(sizeof(ne)+sizeof(SGT::a))/1024/1024<<endl;
    117     memset(s,'a',sizeof(s));
    118     scanf("%d%d",&n,&q);
    119     for(int i=1;i<=n;i++) scanf("%s",Ti),AC::insert(AC::root,Ti,strlen(Ti));
    120     scanf("%s",s+1);
    121     m=strlen(s+1);
    122     s[m+1]='a';
    123 }
    124 void solve(){
    125     for(int i=1;i<=q;i++){
    126         int op,l,r;
    127         scanf("%d%d%d",&op,&l,&r);
    128         if(op==1){
    129             scanf("%s",str+len);idcnt++;
    130             li[idcnt]=len;len+=strlen(str+len);ri[idcnt]=len-1;
    131             lenth[idcnt]=ri[idcnt]-li[idcnt]+1;
    132             prework(li[idcnt],ri[idcnt],r-l+1);
    133             SGT::modify(1,l,r,idcnt,0,1,(1<<pwlen));
    134         }else{
    135             pii ret=mp(0,0);
    136             ret=SGT::query(1,l,r,ret,1,(1<<pwlen));
    137             printf("%d
    ",ret.se);
    138         }
    139     }
    140     if(len>100000) {puts("Invaid Input2");return;}
    141 }
    142 int main(){
    143      
    144     readin();
    145     AC::buildAC();
    146     if(AC::cnt>50) return puts("Invaid Input1"),0;
    147     for(pwlen=0;(1<<pwlen)<m;pwlen++);
    148     SGT::build(1,1,(1<<pwlen),s,pwlen);
    149     solve();
    150     return 0;
    151 }
    View Code
  • 相关阅读:
    周末现场支持
    变量&字符串
    dead loop、continue & break、while...else语句
    运算符、流程控制、while循环
    二进制、字符编码、浮点数、列表
    字符串操作
    元祖、hash了解、字典、集合
    大数据处理
    含有虚函数的派生类的sizeof
    eclipse UML插件 安装和使用
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8597530.html
Copyright © 2020-2023  润新知