1. 程式人生 > >2018.9.12 離線賽 by CalvinJin

2018.9.12 離線賽 by CalvinJin

T1——gcd(3915)

Description:

給你兩個數A,B,求gcd(An+Bn,AB)mod(109+7).特殊地,gcd(0,x)=x. A,B,n1018,BA

Solution:

  • 關於此題,不知道是被題面誤導要因式分解,還是被NOIP2017D1T1所敏感地去打表…
  • 反正一開始就沒想到正解上,接近自閉…
  • 但當開始走投無路的去肉模擬這個玩意的時候gcd(An+Bn,AB),發現推了一次得到gcd(
    AB,(An+Bn)mod(AB))
    ,就感覺這個好像就是將gcd肉拆一次,再次gcd
  • 真的無語…有點腦筋急轉彎的味道…

Code:

#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t)for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t)for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t)for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define db double #define ll long long #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f3f3f #define MINF 0xc0c0c0c0 #define Sz(a) sizeof(a) #define mcl(a,b) memset(a,b,Sz(a)) #define mcp(a,b) memcpy(a,b,Sz(b)) #define pb push_back #define fi first #define se second template<class T>inline bool chkmin(T &x,T y){return
y<x?x=y,1:0;} template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;} typedef pair<int,int>PII; template<class T>inline void Rd(T &x){ x=0;char c; while((c=getchar())<48); do x=(x<<1)+(x<<3)+(c^48); while((c=getchar())>47); } #define mod 1000000007 ll A,B,K; ll gcd(ll x,ll y){return !y?x:gcd(y,x%y);} struct p50{ ll Pow(ll a,ll b){ ll x=1; while(b){ if(b&1)x=x*a%mod; b>>=1,a=a*a%mod; } return x; } void solve(){ ll X=A-B; ll Y=Pow(A,K)+Pow(B,K); if(!X)printf("%lld\n",Y%mod); else { ll d=gcd(X,Y)%mod; printf("%lld\n",d); } } }p1; struct p100{ ll Mul(ll x,ll y,ll P){ ll res=0; while(y){ if(y&1)res=(res+x)%P; y>>=1; x=(x<<1)%P; } return res; } ll Pow(ll a,ll b,ll P){ ll x=1; while(b){ if(b&1)x=Mul(x,a,P); a=Mul(a,a,P); b>>=1; } return x; } void solve(){ ll X=A-B; if(!X)printf("%lld\n",(Pow(A,K,mod)+Pow(B,K,mod))%mod); else { ll Y=(Pow(A,K,X)+Pow(B,K,X))%X; printf("%lld\n",gcd(X,Y)%mod); } } }p2; int main(){ // freopen("gcd.in","r",stdin); // freopen("gcd.out","w",stdout); Rd(A),Rd(B),Rd(K); if(A<=9 && B<=9 && K<=9)p1.solve(); else p2.solve(); return 0; }

T2——triangle(3916)

Description:

有一個長度為n的序列{A},表示木棒的長度.我們將用這些木棒拼出周長最大的三角形. 那麼有q個操作.

  1. op=1,pos,val.將Apos=val
  2. op=2,l,r.對區間[l,r]進行詢問最大的三角形周長. n,q105,Ai109

Solution:

  • 對於三角形的周長問題,最近也是頻繁遇到.
  • 而此題是帶單點修改的.那麼顯然是用線段樹解決.
  • 那麼線段樹的關鍵還是合併問題.
  • 我們發現,在樹上直接存答案是不太現實的.
  • 那麼我們只能是存該區間的一些木棒.
  • 而我們要的是最大的周長,那麼關鍵字一定是>.
  • 這裡,我覺得自己的做法還是偏無腦的做法.
  • 因為分析修改的q,對於每個區間影響的Ai,其實是隻有logq個.
  • 那麼我們就在樹上存上每個區間的前logqAi即可.
  • 最後詢問暴力來取max.

Code:

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast")
#define REP(i,f,t)for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t)for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t)for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define db double
#define ll long long 
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f
#define MINF 0xc0c0c0c0
#define Sz(l) sizeof(l)
#define mcl(l,b) memset(l,b,Sz(l))
#define mcp(l,b) memcpy(l,b,Sz(b))
#define pb push_back
#define fi first
#define se second
template<class T>inline bool chkmin(T &x,T y){return y<x?x=y,1:0;}
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
typedef pair<int,int>PII;
template<class T>inline void Rd(T &x){
    x=0;char c;
    while((c=getchar())<48);
    do x=(x<<1)+(x<<3)+(c^48);
    while((c=getchar())>47);
}

#define N 100002

int n,q;
int A[N];

struct p40{

    int tmp[N],cnt;

    void solve(){
        int op,a,b;
        ll ans;
        while(q--){
            Rd(op),Rd(a),Rd(b);
            if(op==1)A[a]=b;
            else {
                cnt=0;
                REP(i,a,b)tmp[++cnt]=A[i];
                sort(tmp+1,tmp+1+cnt);

                ans=0;
                REP(i,1,cnt-2){
                    REP(j,i+1,cnt-1){
                        int k=lower_bound(tmp+j+1,tmp+cnt+1,tmp[j])-tmp;
                        if(tmp[i]+tmp[j]>tmp[k])chkmax(ans,(ll)tmp[i]+tmp[j]+tmp[k]);
                    }
                }

                printf("%lld\n",ans);
            }                       
        }
    }
}p1;

struct p100{

    #define lson L,mid,p<<1
    #define rson mid+1,R,p<<1|1

    struct node{
        int L,R;
        int len,l[50];
    }tree[N<<2],ans;

    node Up(node L,node R){
        node res;
        res.L=L.L,res.R=R.R;
        res.len=min(47,L.len+R.len);

        int p1=1,p2=1;
        REP(i,1,res.len){
            if(p1<=L.len && p2<=R.len) res.l[i]=(L.l[p1]>R.l[p2]?L.l[p1++]:R.l[p2++]);
            else if(p1<=L.len)res.l[i]=L.l[p1++];
            else res.l[i]=R.l[p2++];
        }
        return res;
    }

    void build(int L,int R,int p){
        tree[p].L=L,tree[p].R=R;
        if(L==R){
            tree[p].len=1;
            tree[p].l[1]=A[L];
            return;
        }
        int mid=(L+R)>>1;
        build(lson),build(rson);
        tree[p]=Up(tree[p<<1],tree[p<<1|1]);
    }

    void update(int p,int x,int v){
        if(tree[p].L==tree[p].R){
            tree[p].l[1]=v;
            return;
        }
        int mid=(tree[p].L+tree[p].R)>>1;
        if(x<=mid)update(p<<1,x,v);
        else update(p<<1|1,x,v);
        tree[p]=Up(tree[p<<1],tree[p<<1|1]);
    }

    node query(int L,int R,int p){
        if(tree[p].L==L && tree[p].R==R)return tree[p];
        int mid=(tree[p].L+tree[p].R)>>1;
        if(R<=mid)return query(L,R,p<<1);
        else if(L>mid)return query(L,R,p<<1|1);
        else return Up(query(lson),query(rson));
    }

    void solve(){
        build(1,n,1);
        int op,a,b;
        while(q--){
            Rd(op),Rd(a),Rd(b);
            if(op==1)update(1,a,b);
            else {
                ans=query(a,b,1);
                ll res=0;
                REP(i,3,ans.len) if(ans.l[i]+ans.l[i-1]>ans.l[i-2]) chkmax(res,1ll*ans.l[i]+ans.l[i-1]+ans.l[i-2]);
                printf("%lld\n",res);
            }
        }
    }
}p2;

int main(){

//  freopen("triangle.in","r",stdin);
//  freopen("triangle.out","w",stdout);

    Rd(n),Rd(q);
    REP(i,1,n)Rd(A[i]);

    if(n<=100 && q<=100)p1.solve();
    else p2.solve();

    return 0;
}

T3——cactus(3916)

Description:

給出n個點,m條邊的僅存在簡單環的圖.求對於每個點,刪掉mn+1條邊(即變為一棵樹)後的到其它點的最大值的最小值. n500000

Solution:

  • 對於題面一上來就仙人掌的…表示很虛啊..
  • 但是切完分,發現暴力+圖本為一棵樹的解法差不多就是正解了吧…
  • 只不過這裡存在簡單環.我們先tarjan縮點.這裡我順便就用