9.10模拟赛

T1.bug

可以求出s(x)的表达式,s(x)=9*pow(10,(x-1)/2)

然后可以看出sum(x)具有一定的规律,开头是(x-2+(x%2)),然后是一些7,最后是一个9

构造这样一个数,需要用到9的逆元,注意到9和23333互质,用欧拉定理求即可

单次询问复杂度O(logn)

#include<iostream>
#include<cstdlib>
#include<cstdio>

using namespace std;

typedef long long ll;

inline ll rd(){
    ll ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MOD = 233333;
const ll inv = 29892;
ll qpow(ll x,ll y){
    register ll ret=1ll;
    while(y){
        if(y&1)(ret*=x)%=MOD;
        (x*=x)%=MOD;
        y>>=1ll;
    }
    return ret;
}

ll T,n;

void out(ll x){
    if(!x)return;
    out(x/10);
    putchar(x%10+'0');
}

inline void solve(){
    n=rd();
    ll v=(n-2+(n&1));
    ll tmp=qpow(10ll,(v/2)+1);
    ll ans=(tmp*v);
    tmp--;
    if(tmp<0)tmp+=MOD;
    tmp*=181482ll;
    ans+=tmp;
    out((ans+2)%MOD);
    putchar('
');
//    printf("%lld
",(ans+2)%MOD); 
}

int main(){
    freopen("bug.in","r",stdin);
    freopen("bug.out","w",stdout);
    T=rd();
    while(T--)solve();
    return 0;
}
View Code

T2.shopping

考虑两个区间的关系

1.相离:互不影响,都选择

2.包含:先选大区间

3.相交:设两个区间的和A=a+b,B=b+c,比较两边平方,发现最终取决于a和c的大小,也就是A和B的大小,因此选和更大的区间

相交的情况可以推广到任意多个区间相交,类比冒泡排序的思想,可以用区间和为关键字排序,找出选择序列

然后就是如何统计答案了,类似疯狂的馒头,用并查集维护,复杂度O(n)

总复杂度O(nlogn)

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>

using namespace std;

typedef long long ll;

inline ll rd(){
    ll ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

int n,m;

const int MAXN=5005;

int a[MAXN],s[MAXN];

struct Ask{
    int l,r,sum;
    bool operator <(const Ask &rhs)const{
        return sum>rhs.sum;
    }
}q[1000005];
int fa[MAXN];
int fnd(int x){return x==fa[x]?x:fa[x]=fnd(fa[x]);}
void cat(int x,int y){x=fnd(x);y=fnd(y);if(x==y)return;fa[x]=y;}


int L[MAXN],R[MAXN];

int vis[MAXN],used[MAXN];
int ans=0;
void dfs(int dp,int sum){
    if(dp==m+1){ans=max(ans,sum);return;}
    for(int i=1;i<=m;i++){
        if(vis[i])continue;
        int u=L[i],v=R[i];
        int tmp=0,t=0;
        for(int j=u;j<=v;j++){
            if(used[j]){
                t+=tmp*tmp;
                tmp=0;
                continue;
            }
            tmp+=a[j];
            used[j]=dp;
        }
        if(tmp) t+=tmp*tmp;
        dfs(dp+1,sum+t);
        for(int j=u;j<=v;j++){
            if(used[j]==dp) used[j]=0;
        }
    }        
}

void violence(){
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=m;i++){
        L[i]=rd();R[i]=rd();
    }
    dfs(1,0);
    cout<<ans;
}

int main(){
    freopen("shopping.in","r",stdin);
    freopen("shopping.out","w",stdout);
//    freopen("testdata.in","r",stdin);
    n=rd();m=rd();
    
    if(m<=6&&n<=1000) return violence(),0;
    
    for(register int i=1;i<=n;i++){
        a[i]=rd();s[i]=s[i-1]+a[i];
        fa[i]=i;
    }
    fa[n+1]=n+1;
    int x,y;
    for(register int i=1;i<=m;i++){
        x=q[i].l=rd();y=q[i].r=rd();
        q[i].sum=s[y]-s[x-1];
    }
    sort(q+1,q+1+m);
    ll ans=0ll;
    for(register int i=1;i<=m;i++){
        int u=q[i].l,v=q[i].r;
        ll tmp=0ll;
        for(register int j=fnd(u);j<=v;j=fnd(j)){
            tmp+=a[j];
            cat(j,j+1);
            if(fa[j]!=j+1) ans+=tmp*tmp,tmp=0ll;
        }
        if(tmp) ans+=tmp*tmp;
    }
    cout<<ans;
    return 0;
}
View Code

T3.mo

没什么思路,字符串方面的知识还是太少,要是会写SAM就好了

写了O(n^2)的暴力,数据水放过去了

正解后缀数组+RMQ,待学习

未经许可,禁止搬运。
原文地址:https://www.cnblogs.com/ghostcai/p/9630089.html