SDOI2011

打地鼠

它竟然是道蓝题首先对于检验某种规格的锤子是否可行,一定是要从左上角开始消除,证明很简单,不再赘述。当然暴力枚举长宽的效率是很低的,让我们加 yi 点点小优化。

  1. 对于一种规格,若它的面积不能被总数整除,肯定不行。
  2. 其实上面那个优化已经够了,但优化永无止境,若有一个大面积可行,那么小面积肯定不优。
  3. 若你精(xian)益(de)求(dan)精(teng),在检验时,还可以差分优化。
#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x){
    T ch=getchar(),xx=1;x=0;
    while(!isdigit(ch)) xx=ch=='-'?-1:xx,ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    x*=xx;
}
template<typename T>inline void prt(T x){
    if(x>9) prt(x/10);
    putchar(x%10|48);
}
#define N 110
int f[N][N],a[N][N];
int n,m,ans,s,sum;
int get(int x,int y){
    memcpy(a,f,sizeof a);
    int ret=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            if(a[i][j]==0) continue;
            else if(a[i][j]>0 && i+x-1<=n && j+y-1<=m){
                int z=a[i][j];ret+=z;
                for(int k=i;k<=i+x-1;++k)
                    a[k][j]-=z,a[k][j+y]+=z;//差分
            } else return INT_MAX;
        }
    return ret;
}
int main(){
    read(n),read(m);
    for(int i=1;i<=n;++i)
        for(int j=1,x,y=0;j<=m;++j)
            read(x),f[i][j]=x-y,y=x,sum+=x;//差分
    ans=get(1,1);s=1;
    for(int i=n;i>=1;--i){
        if(sum%i) continue;//剪枝 1
        for(int j=m;j>=1;--j){
            if(i*j<s) break;//剪枝 2
            if(sum%(i*j)) continue;//剪枝 1
            int t=get(i,j);
            if(t!=INT_MAX){
                ans=min(t,ans);
                s=i*j;//剪枝 2
                break;
            }
        }
    }
    prt(ans);
}

消防

很好的一道理解树的直径的题。
首先让我们思考一个问题,路径该在哪? 答案是一定在直径上。
证明:
假设路径不完全在直径上,那离路径最远的点一定是直径的两个端点之一(为什么?因为它是直径,最远的点不在直径上还能在哪?),又因为是直径,那总能找到一个点比直径近,我们又想尽量使最大值变小,那为什么不让路径在直径上,让这个点作为答案呢?
证毕。
那既然路径在直径上,那答案就出来了。
k k k 是直径上的点, D k D_k Dk k k k 不经过直径能到达最远的点, S k S_k Sk 表示直径上点的集合, q , p q,p q,p 为选的路径的端点, 1 1 1 t t t 为直径的两个端点。答案即是 max ⁡ ( max ⁡ i ≤ k < j { D k } , d i s t ( 1 , q ) , d i s t ( p , t ) ) \max(\max_{i\leq k<j}\{D_k\},dist(1,q),dist(p,t)) max(ik<jmax{Dk},dist(1,q),dist(p,t))由于直径的最长性,上式可以变为 max ⁡ ( max ⁡ k ∈ S k { D k } , d i s t ( 1 , q ) , d i s t ( p , t ) ) \max(\max_{k\in S_k}\{D_k\},dist(1,q),dist(p,t)) max(kSkmax{Dk},dist(1,q),dist(p,t))可见 D k D_k Dk 是一个定值,不随 q , p q,p q,p 变化。而对于 q , p q,p q,p 的枚举,由于范围限定,对于 q q q 而言, p p p 是单调变化的。即最后 O ( n ) O(n) O(n) 扫描一遍就行了。

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x){
    T ch=getchar(),xx=1;x=0;
    while(!isdigit(ch)) xx=ch=='-'?-1:xx,ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    x*=xx;
}
template<typename T>inline void prt(T x){
    if(x>9) prt(x/10);
    putchar(x%10|48);
}
#define N 500010
int head[N],to[N<<1],nxt[N<<1],len[N<<1],cnt;
int fa[N],f[N],d[N],a[N]; 
int n,s,m,temp,ans=0x7f7f7f7f;
bool v[N];
void add(int x,int y,int z) {
    to[++cnt]=y,len[cnt]=z,nxt[cnt]=head[x],head[x]=cnt;
}
void dfs(int x){
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i],z=len[i];
        if(y==fa[x]) continue;
        fa[y]=x;
        d[y]=d[x]+z;
        dfs(y);
    }
}
void pre(){
    dfs(1);
    int x=1,y=1;
    for(int i=1;i<=n;fa[i]=0,++i) if(d[i]>d[x]) x=i;
    d[x]=0;
    dfs(x);
    for(int i=1;i<=n;i++) if(d[i]>d[y]) y=i;
    for(;y!=x;y=fa[y]) v[y]=1,a[++m]=y;
    v[x]=1;
    a[++m]=x;
}
void get(int x){
    v[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i],z=len[i];
        if(v[y]) continue;
        get(y);
        f[x]=max(f[x],f[y]+z);
    }
}
int main(){
    read(n),read(s);
    for(int i=1,x,y,z;i<n;++i){
        read(x),read(y),read(z);
        add(x,y,z),add(y,x,z);
    }
    pre();
    for(int i=1;i<=m;++i) get(a[i]),temp=max(temp,f[a[i]]);
    for(int i=m,j=m;i;i--){
        while(j && d[a[j]]-d[a[i]]<=s) j--;
        ans=min(ans,max(temp,max(d[a[i]],d[a[1]]-d[a[j+1]])));
    }
    prt(ans);
    return 0;
}

染色

数剖题,详见代码。

#include<bits/stdc++.h>
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;
const int N=100009;
struct node{
    int l,r,lcol,rcol,sum,lz;
}tr[N<<2];
int n,m,tot,cnt,L,R;
int head[N],to[N<<1],nxt[N<<1];
int col[N];
int dep[N],siz[N],fa[N],son[N],top[N],seg[N],rev[N];
template<typename T>inline void read(T &a){
    T ch=getchar(),f=1;
    for(a=0;!isdigit(ch);ch=getchar()) f=ch=='-' ? -1 : f;
    for(;isdigit(ch);ch=getchar()) a=(a<<3)+(a<<1)+ch - '0';
    a *=f;
}
template<typename T>inline void print(T x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x / 10);
    putchar(x % 10+'0');
}
inline int add(int u,int v){
    to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
}
inline void dfs(int x,int f){
    dep[x]=dep[f]+1;
    siz[x]=1;
    fa[x]=f;
    for(int i=head[x];i;i=nxt[i]){
        int v=to[i];
        if(v==f) continue;
        if(!dep[v]){
            dfs(v,x);
            siz[x]+=siz[v];
            if(siz[v]>siz[son[x]])
                son[x]=v;
        }
    }
}
inline void dfs2(int x,int f){
    if(son[x]){
        seg[son[x]]=++tot;
        rev[tot]=son[x];
        top[son[x]]=top[x];
        dfs2(son[x],x);
    }
    for(int i=head[x];i;i=nxt[i]){
        int v=to[i];
        if(!top[v]){
            top[v]=v;
            seg[v]=++tot;
            rev[tot]=v;
            dfs2(v,x);
        }
    }
}
inline void build(int x,int l,int r){
    tr[x].l=l,tr[x].r=r;
    tr[x].lz=-1;
    if(l==r){
        tr[x].lcol=tr[x].rcol=col[rev[l]];
        tr[x].sum=1;
        return;
    }
    int mid=(l+r)>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    tr[x].sum=tr[lc].sum+tr[rc].sum;
    if(tr[lc].rcol==tr[rc].lcol) tr[x].sum--;
    tr[x].lcol=tr[lc].lcol;
    tr[x].rcol=tr[rc].rcol;
}
inline void pushdown(int x){
    if(tr[x].lz==-1)return;
    tr[lc].lz=tr[rc].lz=tr[x].lz;
    tr[lc].lcol=tr[lc].rcol=tr[x].lz;
    tr[rc].lcol=tr[rc].rcol=tr[x].lz;
    tr[lc].sum=tr[rc].sum=1;
    tr[x].lz=-1;
}
inline void update(int x,int l,int r,int val){
    if(tr[x].l>r || tr[x].r<l)    return;
    if(tr[x].l>=l && tr[x].r<=r){
        tr[x].lz=tr[x].lcol=tr[x].rcol=val;
        tr[x].sum=1;
        return;
    }
    pushdown(x);
    update(lc,l,r,val);update(rc,l,r,val);
    tr[x].sum=tr[lc].sum+tr[rc].sum;
    if(tr[lc].rcol==tr[rc].lcol) tr[x].sum--;
    tr[x].lcol=tr[lc].lcol;tr[x].rcol=tr[rc].rcol;
}
inline void change(int x,int y,int z){
    if(dep[x]<dep[y])swap(x,y);
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
        update(1,seg[fx],seg[x],z);
        x=fa[top[x]],fx=top[x];
    }
    if(dep[x]>dep[y]) swap(x,y);
    update(1,seg[x],seg[y],z);
}
inline int query(int x,int l,int r){
    if(tr[x].l>r || tr[x].r<l) return 0;
    if(tr[x].l==l) L=tr[x].lcol;
    if(tr[x].r==r) R=tr[x].rcol;
    if(tr[x].l>=l && tr[x].r<=r) return tr[x].sum;
    pushdown(x);
    int ans=query(lc,l,r)+query(rc,l,r);
    if(tr[lc].l>r || tr[lc].r<l || tr[rc].l>r || tr[rc].r<l) return ans;
    if(tr[lc].rcol==tr[rc].lcol) ans--;
    return ans;
}
inline int ask(int x,int y){
    int ans=0,lca,tmpx=x,tmpy=y,pre=-1;
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]<dep[fy])
            swap(x,y),swap(fx,fy);
        x=fa[top[x]],fx=top[x];
    }
    lca=dep[x]>dep[y] ? y : x;
    x=tmpx,y=tmpy;
    while(top[x]!=top[lca]){
        ans+=query(1,seg[top[x]],seg[x]);
        if(R==pre) ans--;
        pre=L;
        x=fa[top[x]];
    }
    ans+=query(1,seg[lca],seg[x]);
    if(R==pre) ans--;
    pre=-1;
    while(top[y]!=top[lca]){
        ans+=query(1,seg[top[y]],seg[y]);
        if(R==pre) ans--;
        pre=L;
        y=fa[top[y]];
    }
    ans+=query(1,seg[lca],seg[y]);
    if(R==pre) ans--;
    return ans-1;
}
int a,b,c;
char opt[2];
int main(){
    read(n),read(m);
    for(int i=1;i<=n;i++) read(col[i]);
    for(int i=1;i<n;i++){
        read(a),read(b);
        add(a,b),add(b,a);
    }
    dfs(1,0);
    seg[1]=rev[1]=top[1]=tot=1;
    dfs2(1,0);
    build(1,1,n);
    while(m--){
        scanf("%s",opt);
        read(a),read(b);
        if(opt[0]=='C')
            read(c),change(a,b,c);
        else
            print(ask(a,b)),putchar('\n');
    }
    return 0;
}

计算器

快速幂, e x g c d exgcd exgcd B a b y S t e p , G i a n t S t e p Baby Step,Giant Step BabyStep,GiantStep 板题。

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &x){
    T ch=getchar();x=0;
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
}
template<typename T>inline void prt(T x){
    if(x>9) prt(x/10);
    putchar(x%10|48);
}
int qpow(int x,int y,int p){
    int ret=1;
    while(y){
        if(y&1) ret=1ll*ret*x%p;
        x=1ll*x*x%p;
        y>>=1;
    }
    return ret;
}
int exgcd(int a,int b,int &x,int &y){
    if(b==0){x=1,y=0;return a;} 
    int d=exgcd(b,a%b,x,y);
    int z=x;x=y;y=z-y*(a/b);
    return d;
}
int BSGS(int a,int b,int p) {
    map<int,int> hash;
    hash.clear();
    int t=(int)sqrt(p)+1;
    for(int i=0;i<t;i++) {
        int val=1ll*b*qpow(a,i,p)%p;
        hash[val]=i;
    }
    a=qpow(a,t,p);
    if(!a) return b?-1:1;
    for(int i=0;i<=t;i++) {
        int val=qpow(a,i,p);
        int j=hash.find(val)==hash.end() ? -1:hash[val];
        if(j>=0 && i*t>=j) return i*t-j;
    }
    return -1;
}
int T,K,y,z,p;
int main(){
    for(read(T),read(K);T--;){
        int x,t,d;
        read(y),read(z),read(p);
        if(K==1) prt(qpow(y%p,z%(p-1),p)),puts("");
        if(K==2){
            d=exgcd(y,p,x,t);
            if(z%d) puts("Orz, I cannot find x!");
            else prt((1ll*x*z/d%p+p)%p),puts("");
        }
        if(K==3){
            d=BSGS(y,z,p);
            if(d==-1) puts("Orz, I cannot find x!");
            else prt(d),puts("");
        }
    }
}

更新中…

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值