10 17

  今天 海星 可是 好像沒有作到應該作到的事情 如 想出正解 如 對拍 如 仔細檢查qwq.node

今天得分 105 T1 100 T2 5分 T3 自閉 不會 爆零ios

 

關於本題 因爲狀態不存在環什麼的 因此好作一點有 起點和終點 都是 一個狀態 因此也好作一點。c++

起點 必須拿一張牌 也就是開始拿一張牌 而後發現終點是n+1張牌 因此 有終點 只須要枚舉當前獲得第i張牌的機率 及 算出來指望 就行啦。ide

如 到k張牌中止的機率是 p(x=k) = 1*(n-1)/n *(n-2)/n *(n-3)/n...*(n-(k-2))/n *(k-1)/n...ui

那麼指望顯然 就是 E(x=k)=p(x=k)*k; 求個累和便可。能夠發現這個式子每次變化都是有規律的因此咱們O(n)遞推便可。spa

考慮dp 設f[i] 表示已經獲得了i張牌此時還須要拿多少張牌才能中止的指望牌數。3d

那麼 f[n]=1; 那對於一個普通的i來講 f[i]=i/n+(n-i)/n*(f[i+1]+1);指針

發現直接推到 f[0] 便可。這個我有代碼。code

//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<iomanip>
#include<cctype>
#include<cstdio>
#include<deque>
#include<utility>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#define INF 2147483646
#define ll long long
#define db double
#define pii pair<ll,ll>
#define mk make_pair
#define us unsigned
#define min(x,y) ((x)>(y)?(y):(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define mod 998244353ll
using namespace std;
char *fs,*ft,buf[1<<15];
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
const int MAXN=10000010;
ll N=10000001,Q;
ll f[MAXN],n;//f[i]表示已經摸出了i張牌還須要摸的牌數
ll jc,in[MAXN];
int inv[MAXN];
inline ll ksm(ll b,ll p)
{
    ll ans=1;
    while(p)
    {
        if(p&1)ans=(ans*b)%mod;
        b=b*b%mod;
        p=p>>1;
    }
    return ans;
}
inline void prepare()
{
    jc=1;
    for(int i=1;i<=N;++i)jc=jc*i%mod;
    inv[N]=ksm(jc,mod-2);
    for(int i=N-1;i>=0;--i)inv[i]=((ll)inv[i+1])*(i+1)%mod;
    jc=1;
    for(int i=1;i<=N;++i)
    {
        in[i]=(inv[i]*jc)%mod;
        jc=jc*i%mod;
    }
}
signed main()
{
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    Q=read();prepare();
    while(Q--)
    {
        n=read();f[n]=1;
        for(int i=n-1;i>=0;--i)
        {
            f[i]=((i*in[n])%mod+(((n-i)*in[n])%mod)*(f[i+1]+1))%mod;
        }
        printf("%lld\n",f[0]);
    }
    return 0;
}
View Code

惟一不足的是逆元是3n的複雜度 是能夠O(n) 推逆元的 可是我忘了qwq,仍是考試事後再複習一下比較好。blog

這裏我扒一篇題解的證實過來 仍是很容易看出來的。

//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<iomanip>
#include<cctype>
#include<cstdio>
#include<deque>
#include<utility>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#define ll long long
#define INF 1000000000
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define us unsigned
#define mod 1000000007
using namespace std;
char *fs,*ft,buf[1<<15];
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin)),fs==ft)?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
const int MAXN=3000010;
int n,p;
ll in[MAXN];
int main()
{
    freopen("1.in","r",stdin);
    n=read();p=read();in[1]=1;
    for(int i=2;i<=n;++i)in[i]=(p-p/i)*in[p%i]%p;
    for(int i=1;i<=n;++i)printf("%lld\n",in[i]);
    return 0;
}
View Code

這道題 就比較...我很震驚的是我居然沒有思考出來 好像沒有把簡單的模型抽出來的樣子。 考慮詢問都是1的點無非就是在本身的子樹中尋找一個dis大於當前詢問的東西而後取min。

這個操做固然能夠主席樹作。但是考慮 對於任意一個點的詢問k呢 那就是 k+disx 而後再在x的子樹種尋找qwq。

如何限定區間?可持久化主席樹?很不行主席樹 的前綴和不支持取min操做 換句話說取min操做沒有區間可加性。考慮主席樹合併。

很穩可是觀察此題 頗有可能被卡 複雜度在 nlogn~nlognlogn 之間 因此容易被卡死。

換個思路 能夠把詢問離線而後把咱們這些節點也丟進去而後排序這樣就少了主席樹限定大小的問題了只須要維護區間性的問題和區間取min的問題了。

能夠dfs序建樹就能夠解決這個問題了qwq。 之後腦子要靈光一點Y。複雜度nlogn.

//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<iomanip>
#include<cctype>
#include<cstdio>
#include<deque>
#include<utility>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#define ll long long
#define INF 1000000000
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define us unsigned
#define mod 1000000007
#define l(p) t[p].l
#define r(p) t[p].r
#define sum(p) t[p].sum
#define zz p<<1
#define yy p<<1|1
using namespace std;
char *fs,*ft,buf[1<<15];
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,dp=1;char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')dp=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*dp;
}
const int MAXN=2010,maxn=700010;
int T,Q,n,len,id,top,cnt,rt;
int dis[maxn],d[maxn],dfn[maxn],sz[maxn],ans[maxn];
int lin[maxn],nex[maxn<<1],ver[maxn<<1],e[maxn<<1];
struct jl
{
    int op;
    int x,v;
}s[maxn<<1];
struct wy
{
    int l,r;
    int sum;
}t[maxn<<2];
inline void add(int x,int y,int z)
{
    ver[++len]=y;
    nex[len]=lin[x];
    lin[x]=len;
    e[len]=z;
}
inline void dfs(int x,int father)
{
    dfn[x]=++id;sz[x]=1;
    for(int i=lin[x];i;i=nex[i])
    {
        int tn=ver[i];
        if(tn==father)continue;
        d[tn]=d[x]+1;
        dis[tn]=dis[x]+e[i];
        dfs(tn,x);
        sz[x]+=sz[tn];
    }
}
inline int cmp(jl a,jl b){return a.v==b.v?a.op<b.op:a.v>b.v;}
inline void build(int p,int l,int r)
{
    l(p)=l;r(p)=r;
    if(l==r)
    {
        sum(p)=INF;
        return;
    }
    int mid=(l+r)>>1;
    build(zz,l,mid);
    build(yy,mid+1,r);
    sum(p)=min(sum(zz),sum(yy));
}
inline void change(int p,int x,int k)
{
    if(l(p)==r(p))
    {
        sum(p)=k;
        return;
    }
    int mid=(l(p)+r(p))>>1;
    if(x<=mid)change(zz,x,k);
    else change(yy,x,k);
    sum(p)=min(sum(zz),sum(yy));
}
inline int ask(int p,int l,int r)
{
    if(l<=l(p)&&r>=r(p))return sum(p);
    int mid=(l(p)+r(p))>>1;
    int ansl=INF,ansr=INF;
    if(l<=mid)ansl=ask(zz,l,r);
    if(r>mid)ansr=ask(yy,l,r);
    return min(ansl,ansr);
}
int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    T=read();n=read();
    for(int i=2;i<=n;++i)
    {
        int x,y,z;
        x=read();y=read();z=read();
        add(x,y,z);add(y,x,z);
    }
    dfs(1,0);
    Q=read();
    for(int i=1;i<=Q;++i)
    {
        int x,k;
        x=read();k=read();
        s[++top]=(jl){i,x,dis[x]+k};
    }
    for(int i=1;i<=n;++i)s[++top]=(jl){0,i,dis[i]};
    sort(s+1,s+1+top,cmp);
    build(1,1,id);
    for(int i=1;i<=top;++i)
    {
        //cout<<s[i].op<<' '<<s[i].v<<endl;
        if(s[i].op)
        {
            int w=ask(1,dfn[s[i].x],dfn[s[i].x]+sz[s[i].x]-1);
            if(w==INF)ans[s[i].op]=-1;
            else ans[s[i].op]=w-d[s[i].x];
        }
        else change(1,dfn[s[i].x],d[s[i].x]);
    }
    for(int i=1;i<=Q;++i)printf("%d\n",ans[i]);
    return 0;
}
View Code

題解還給出了一個比較nb的方法 考慮對於大小問題排過序以後直接O(n)掃描 。可是這個掃描也具備區間的性質因此能夠考慮CDQ分治了。

三維偏序問題 1 子樹內外的關係 2 dis大小的問題 處理好這三個我認爲就行了。

其中其中對於 1 能夠dfs序判斷或者採用O(1) LCA的方法判斷 對於2 能夠直接在外面排好序 而後內部直接歸併。統計答案的時候直接指針暴力掃。

複雜度nlogn TAT

說好了要講題解 講到了CDQ分治qwq 題解中是這樣解決區間的問題的 考慮線段樹分治把每一個問題分紅logn個區間

而直接 暴力遞歸線段樹 回溯時歸併一下點 而後就完成了 複雜度 Qlogn+nlogn。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#define P puts("lala")
#define cp cerr<<"lala"<<endl
#define ln putchar('\n')
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
inline int read()
{
    char ch=getchar();int g=1,re=0;
    while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
    while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
    return re*g;
}
typedef long long ll;
typedef pair<int,int> pii;

const int N=700009;
int head[N],cnt=0;
struct node
{
    int to,next,w;
}e[N<<1];
inline void add(int x,int y,int w)
{
    e[++cnt]=(node){y,head[x],w}; head[x]=cnt;
    e[++cnt]=(node){x,head[y],w}; head[y]=cnt;
}

int n,q;

const int inf=0x3f3f3f3f;
struct ASK
{
    int id,x,k,ans;
}ask[N];
bool operator < (ASK a,ASK b)
{
    return a.k<b.k;
}


int dep[N],dis[N],dfn[N],efn[N],tot=0,is[N];
void dfs(int u,int fa,int dp,int ds)
{
    dep[u]=dp; dis[u]=ds; dfn[u]=++tot; is[tot]=u;
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa) continue;
        dfs(v,u,dp+1,ds+e[i].w);
    }
    efn[u]=tot;
}

pii p[N]; // (ds,dp)
vector<int>Q[N<<2];
void hang(int o,int l,int r,int x,int y,int i)
{
    if(x<=l&&r<=y) {Q[o].pb(i); return ;}
    int mid=l+r>>1;
    if(x<=mid) hang(o<<1,l,mid,x,y,i);
    if(y>mid) hang(o<<1|1,mid+1,r,x,y,i);
}
pii tmp[N];
int sufmin[N];
void solve(int o,int l,int r)
{
    if(l==r)
    {
        for(int i=0,sz=Q[o].size();i<sz;++i)
        {
            int u=Q[o][i];
            if(p[l].fi>=ask[u].k) 
                ask[u].ans=min(ask[u].ans,p[l].se);
        }
        return ;
    }
    int mid=l+r>>1;
    solve(o<<1,l,mid); solve(o<<1|1,mid+1,r);
    int i=l,j=mid+1,k=l;
    while(i<=mid&&j<=r)
        if(p[i]<p[j]) tmp[k]=p[i],i++,k++;
        else tmp[k]=p[j],j++,k++;
    while(i<=mid) tmp[k]=p[i],i++,k++;
    while(j<=r) tmp[k]=p[j],j++,k++;
    for(i=l;i<=r;++i) p[i]=tmp[i];
    
    sufmin[r]=p[r].se;
    for(i=r-1;i>=l;--i) sufmin[i]=min(sufmin[i+1],p[i].se);
    
    int p1=l,p2=0,sz=Q[o].size();
    for(;p2<sz;++p2)
    {
        int u=Q[o][p2];
        while(p1<=r&&p[p1].fi<ask[u].k) p1++;
        if(p1<=r) ask[u].ans=min(ask[u].ans,sufmin[p1]);
        else break;
    }
}

int Ans[N];

void wj()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
}
int main()
{
    wj();
    int id=read();
    n=read();
    for(int i=1;i<n;++i)
    {
        int x=read(),y=read(),w=read();
        add(x,y,w);
    }
    dfs(1,0,0,0);
    q=read();
    for(int i=1;i<=q;++i)
    {
        ask[i].id=i;
        ask[i].x=read(); ask[i].k=read();
        ask[i].ans=inf;
        ask[i].k+=dis[ask[i].x];
    }
    sort(ask+1,ask+q+1);
    for(int i=1;i<=q;++i) 
        hang(1,1,n,dfn[ask[i].x],efn[ask[i].x],i);
    for(int i=1;i<=n;++i) p[i]=pii(dis[is[i]],dep[is[i]]);
    solve(1,1,n);
    for(int i=1;i<=q;++i) 
    {
        if(ask[i].ans==inf) Ans[ask[i].id]=-1;
        else Ans[ask[i].id]=ask[i].ans-dep[ask[i].x];
    }
    for(int i=1;i<=q;++i) printf("%d\n",Ans[i]);
    return 0;
}
std

我啥都不會 啥都不懂qwq 咕了qwq。

相關文章
相關標籤/搜索