20190915杂题选讲

Posted psychicboom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20190915杂题选讲相关的知识,希望对你有一定的参考价值。

T1

\(b_1=p_1^a_1p_2^a_2…p_n^a_n\),显然答案最大为\(\sum a_i\)

考虑让\(\sum a_i\)最大,那\(b_1\)不能有有超过5的质因子,因为\(2^2<5\)。3的个数最多也只有一个,因为\(2^3<3^2\)

于是就可以dp,设\(f[i][j][k]\)表示填到第i个数,gcd可以表示为\(2^j3^k\)的答案,分类讨论转移一下,最后答案为\(f[n][0][0]\)

code:

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
#define il inline 
#define For(i,x,y) for(int i=(x);i<=(y);++i) 
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define mod 1000000007
using namespace std;
int f[N][20][2],n,_2[N],_3[N],lim2;

int main()
    int n;
    scanf("%d",&n);_2[0]=1;
    int x=log2(n);
    For(i,1,x) _2[i]=_2[i-1]*2%mod;
    for(int bit=0,i=1;i<=n;i*=3,bit++) _3[bit]=i;
    f[1][x][0]=1;
    if((1<<(x-1))*3<=n) f[1][x-1][1]=1;
    For(i,2,n)
        Rof(j,x,0)
            Rof(k,(n>=3),0)
                if(_2[j]*_3[k]<=n)
                    (f[i][j][k]+=1ll*f[i-1][j][k]*max(0ll,1ll*n/(_2[j]*_3[k])-i+1)%mod)%=mod;
                    if(j>0) (f[i][j-1][k]+=1ll*f[i-1][j][k]*(1ll*n/(_2[j-1]*_3[k])-n/(_2[j]*_3[k]))%mod)%=mod;
                    if(k>0) (f[i][j][k-1]+=1ll*f[i-1][j][k]*(1ll*n/(_2[j]*_3[k-1])-n/(_2[j]*_3[k]))%mod)%=mod;                  
                
                           
        
    printf("%d\n",f[n][0][0]);

T2

先贴个代码,回家补题解

#include <bits/stdc++.h>
#define N 200005
#define ll long long
#define il inline 
#define For(i,x,y) for(int i=(x);i<=(y);++i) 
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define mid ((l+r)>>1)
#define lson t[o].ls,l,mid
#define rson t[o].rs,mid+1,r
#define bas rt,1,n
#define mod 998244353
using namespace std;

int cnt=0,rt=1,_=0;
ll _pow[N];
struct qwq int ls,rs;ll f,g,tf,tg,ans;  t[N<<2];

il void add(ll &x,ll y) x+y>=mod?x=x+y-mod:x=x+y; 
il ll adD(ll x,ll y) return x+y>=mod?x+y-mod:x+y; 
il ll mnS(ll x,ll y) return x-y<0?x-y+mod:x-y; 
il void pushup(int o) t[o].ans=adD(adD(t[t[o].ls].ans,t[t[o].rs].ans),t[o].f); 
void build(int &o,int l,int r)
    o=++cnt;
    t[o].f=t[o].ans=0;
    t[o].g=t[o].tf=t[o].tg=1;
    if(l==r) return;
    build(lson),build(rson);
    pushup(o);

il void pushdowntg(int o,int x)
    t[o].g=1ll*t[o].g*x%mod;
    t[o].tg=1ll*t[o].tg*x%mod;

il void pushdowntf(int o,int x)
    t[o].f=1ll*t[o].f*x%mod;
    t[o].tf=1ll*t[o].tf*x%mod;
    t[o].ans=1ll*t[o].ans*x%mod;    

il void PushDown(int o)
    if(t[o].tf!=1) pushdowntf(t[o].ls,t[o].tf),pushdowntf(t[o].rs,t[o].tf),t[o].tf=1;
    if(t[o].tg!=1) pushdowntg(t[o].ls,t[o].tg),pushdowntg(t[o].rs,t[o].tg),t[o].tg=1;

void modify(int o,int l,int r,int L,int R)
    PushDown(o);
    int _l=t[o].ls,_r=t[o].rs;
    if(L==l && r==R)
        add(t[o].f,_pow[_]);
        pushdowntf(_l,2),pushdowntf(_r,2);
        pushup(o);
        return;
    
    add(t[o].g,_pow[_]);
    if(R<=mid)
        modify(lson,L,R);
        PushDown(_r);
        add(t[_r].f,mnS(_pow[_],t[_r].g)),add(t[_r].g,t[_r].g);
        pushdowntf(t[_r].ls,2),pushdowntf(t[_r].rs,2);
        pushdowntg(t[_r].ls,2),pushdowntg(t[_r].rs,2);
        pushup(_r);
     else if(L>mid)
        modify(rson,L,R);       
        PushDown(_l);
        add(t[_l].f,mnS(_pow[_],t[_l].g)),add(t[_l].g,t[_l].g);
        pushdowntf(t[_l].ls,2),pushdowntf(t[_l].rs,2);
        pushdowntg(t[_l].ls,2),pushdowntg(t[_l].rs,2);
        pushup(_l);
     else modify(lson,L,mid),modify(rson,mid+1,R);
    pushup(o);


int main()
    int n,q,op,l,r;_pow[0]=1;
    scanf("%d%d",&n,&q);
    For(i,1,q) _pow[i]=(_pow[i-1]+_pow[i-1])%mod;
    build(bas);
    while(q--)
        scanf("%d",&op);
        if(op==1)
            scanf("%d%d",&l,&r);
            modify(bas,l,r);
            _++;
         else printf("%lld\n",t[rt].ans);
    
 

T3

\(l=l-1\), \(L=\lfloor l/m \rfloor\), \(R=\lfloor r/m \rfloor\)

最后的式子可以化成\((pre[r]-k*R)-(pre[l]-k*L)-k*\lceil (r\%m-l\%m)/m \rceil\)

获得i对应的左端点时,处理一下i前出现的每个余数对应的最小值就行了

code:

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
#define il inline 
#define For(i,x,y) for(int i=(x);i<=(y);++i) 
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define Edge(x) for(int i=head[x];i;i=e[i].nxt)
#define mod 1000000007
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define ls(x) t[x].ls,l,mid
#define rs(x) t[x].rs,mid+1,r
#define mset(x,y) memset(x,y,sizeof(x))
#define mcpy(x,y) memcpy(x,y,sizeof(x))
using namespace std;
 
ll pre[N],mn[11];
 
int main()
    int n,m,k;
    ll ans=0;
    scanf("%d%d%d",&n,&m,&k);
    mset(mn,0x3f);mn[0]=0;
    For(i,1,n) scanf("%lld",&pre[i]),pre[i]+=pre[i-1];
    For(i,1,n) pre[i]-=1ll*k*(1ll*i/m);
    For(i,1,n)
        For(j,0,min(i-1,m-1))
            ans=max(pre[i]-mn[j]-k*((i%m-j+m-1)/m),ans);
        mn[i%m]=min(mn[i%m],pre[i]);
    
    printf("%lld\n",ans);
 

T4

题解咕了,放个代码:

#include <bits/stdc++.h>
#define N 5000005
#define ll long long
#define il inline 
#define For(i,x,y) for(int i=(x);i<=(y);++i) 
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
#define Edge(x) for(int i=head[x];i;i=e[i].nxt)
#define mod 19260817
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define ls(x) t[x].ls,l,mid
#define rs(x) t[x].rs,mid+1,r
#define mset(x,y) memset(x,y,sizeof(x))
#define mcpy(x,y) memcpy(x,y,sizeof(x))
using namespace std;
char s[N],t[N];
ll f[30],ans=1;
int main()
    int n,m,cnt=0;
    scanf("%d%d\n%s\n%s",&n,&m,s+1,t+1);
    cnt=n;
    For(i,1,m)
        if(t[i]>='A' && t[i]<='Z')
            ll tmp=f[t[i]-'A'];
            f[t[i]-'A']=ans;
            ans=(2ll*ans%mod-tmp+mod)%mod;
         else
            if(!cnt) continue;
            (ans+=1)%=mod;
            (f[s[cnt]-'A']+=1)%=mod;
            cnt--;
        
     printf("%lld\n",ans);

以上是关于20190915杂题选讲的主要内容,如果未能解决你的问题,请参考以下文章

11.28杂题选讲

正睿OI DAY3 杂题选讲

「总结」杂题选讲

杂题选讲

5.30杂题选讲

杂题选讲1