1. 程式人生 > >20181024(字串模擬+three pointer+樹形DP)

20181024(字串模擬+three pointer+樹形DP)

求導

(equation.cpp/c/pas) 【問題描述】 “看上去像⼏幾何問題,實際上是函式問題。” ⽯石神是⼀一位天才數學家。為了能夠將⾃自⼰己的研究進⾏行下去,選擇了在⼀一所⾼高中教書。在⼀一次數學測 驗中,⽯石神給學⽣生出了⼀一道簡單的求導題。題中保證不出現指數相同的項,同時要求不改變求導前後每 ⼀一項的順序。 現在請你給出這道題的正確解答吧。 提⽰示: 1x, x^1, x^0, +x^2, x+x等,不是標準的多項式 x, 1, x^2-x等,是標準的多項式 【輸⼊入】 輸⼊入⽂檔名為equation.in。 輸⼊入僅⼀一⾏行,包含⼀一個標準的多項式,表⽰示原函式。 【輸出】 輸出⽂檔名為equation.out。 輸出⼀一⾏行,包含⼀一個標準的多項式,表⽰示求導後的結果。 【輸⼊入輸出樣例1】 【輸⼊入輸出樣例2】 【資料說明】 對於40%的資料,原函式是單項式 對於100%的資料,原函式不超過100項,保證係數的絕對值≤100000,0≤指數≤100000

equation.in equation.out 2x+1 2 equation.in equation.out 2x^2+3x+1 4x+3 ⻚頁碼:!2/!4 成績調研 (survey.cpp/c/pas) 【問題描述】 “班上所有同學的成績都貼在⿊黑板上。” ⽯石神顯得有些⼼心不在焉。最近恍恍惚惚,還請了兩天假。 這⼀一次的考試,學⽣生的成績分為k等,成績單上按照學⽣生的學號排序。此外,學校要抽⼀一些同學的考 捲去調研,⽯石神將這個任務委派給了你。 抽取的樣本有如下要求: 學號連續的學⽣生 得到1等的學⽣生數量在[l_1,r_1]區間內 得到2等的學⽣生數量在[l_2,r_2]區間內 … 現在請問有多少種抽取樣本的⽅方法。 【輸⼊入】
輸⼊入⽂檔名為survey.in
。 第⼀一⾏行包含兩個數n和k,分別表⽰示班級⼈人數和成績的等第數。 第⼆二⾏行包含n個數a_i(1 ≤ a_i ≤ k),分別表⽰示每個⼈人成績的等第。 接下來k⾏行每⾏行包含兩個數l_k和r_k,分別要求抽取的樣本中,拿到k等第的⼈人數在[l_k,r_k]區間內。 【輸出】 輸出⽂檔名為survey.out。 輸出⼀一⾏行,包含⼀一個整數,表⽰示抽取樣本的⽅方案數。 【輸⼊入輸出樣例1】 【輸⼊入輸出樣例2】 【資料說明】 對於30%的資料,n≤200,k≤200 對於60%的資料,n≤2000,k≤2000 對於100%的資料,n≤200000,k≤200000 survey.in survey.out 3 2 1 1 2 1 2 1 1 2
survey.in
survey.out 5 3 1 2 3 1 2 1 2 1 1 1 1 3

跟蹤

(track.cpp/c/pas) 【問題描述】 “有些真相註定是要⼩小⼼心翼翼深埋⼼心底的,因為答案揭曉的那⼀一刻,也是灰⻜飛煙滅的開始。” ⽯石神從離開學校就被兩個陌⽣生⼈人跟蹤。 整個城市的地圖形成了⼀一棵樹,初始時⽯石神在其中的S點,兩個陌⽣生⼈人分別在P和Q點。 ⽯石神盡⼒力避開,然⽽而卻被窮追不捨。 為了更好地描述他們的移動⽅方法,將其看成3秒為週期(k=0,1,2,3,…): 第3k+1秒⽯石神可以靜⽌止或者移動到任意相鄰的結點,兩個陌⽣生⼈人暫不⾏行動。 第3k+2秒和第3k+3秒兩個陌⽣生⼈人朝著⽯石神的⽅方向⾛走到相鄰的結點,⽯石神暫不⾏行動。 現在請問⽯石神最遲在第⼏幾秒的時候被追上。 【輸⼊入】 輸⼊入⽂檔名為track.in。 第⼀一⾏行包含四個數n S P Q,n表⽰示樹的⼤大⼩小,S P Q含義⻅見問題描述,保證S P Q互不相同。 接下來n-1⾏行每⾏行包含兩個數x和y,表⽰示x與y點之間有⼀一條邊相連。 【輸出】 輸出⽂檔名為track.out。 輸出⼀一⾏行,包含⼀一個整數,表⽰示⽯石神最遲被追上的時間。 【輸⼊入輸出樣例1】 【輸⼊入輸出樣例2】 【資料說明】 對於30%的資料,n≤200 對於60%的資料,n≤2000 對於100%的資料,n≤200000 track.in track.out 4 2 1 3 1 2 2 3 3 4 2 track.in track.out 4 1 2 3 1 2 1 3 1 4 3

題目沒咋複製,看題意概括好了

T1

題意概括:字串大暴力模擬 ,跟求導沒什麼關係 求導: 多項式是由若干個單項式構成的 單項式的一般形式是axbax^b,其中ab都是常數,x是自變數 對於單項式axbax^b求導,結果就是(ab)xb1(ab)x^{b-1} 對於多項式求導,就是把構成它的所有單項式分別求導之後相加 特別地,對於ax0ax^0,即對常數aa求導,結果是00

額根據求導的基本運算,然後字串大模擬,模擬吐了我 注意點 1.負數 2.第一個多項式,當指數不為0時,係數可能為0 3.第一位可能是常數, 以上三條,我全沒注意 27/100

#include<bits/stdc++.h>
#define int long long 
#define R(x,y,z) for(int (x)=(y);(x)<=(z);(x)++)
using namespace std;
int getNum(int l,int r,char* a) {
    int res=0;
    R(i,l,r) res=res*10+a[i]-'0';
    return res;
}
char s[10000],e[105][100];
int len;
bool flg,pos[105];
signed main() {
    scanf("%s",s+1);
    len=strlen(s+1);
    int st=1;
    if(s[1]=='-') st++;
    else pos[1]=true;
    int e_cnt=1,s_cnt=0;
    R(i,st,len)
        if(s[i]=='+'||s[i]=='-') {
            e_cnt++; s_cnt=0;
            if(s[i]=='+') pos[e_cnt]=true;
        } else e[e_cnt][++s_cnt]=s[i];
    R(i,1,e_cnt) {
        int p=1,l=strlen(e[i]+1);
        while(!isalpha(e[i][p])&&p<=l) p++;
        if(p==l+1) {
            if(e_cnt==1) cout<<0;
            continue;
        }
        int a,b;
        a=(p==1?1:getNum(1,p-1,e[i]));
        b=(p==l?1:getNum(p+2,l,e[i]));
        int c=a*b; if(!pos[i]) c=-c;
        int d=b-1;
        if(pos[i]&&flg) cout<<'+';
        if(c!=1||d==0) cout<<c;
        if(d) cout<<'x';
        if(d>1) cout<<'^'<<d;
        flg=true;
    }
    return 0;
}

T2

題意概括:有一個序列,每個元素有一個等第,取一些連續的元素,求這些元素在等第ii[li,ri][li,ri]區間內的方案有多少

threepointersthree pointers 看上去是一個裝逼名字, 但是其實就是維護三個指標 頭指標 尾指標1——指向能滿足條件的從頭指標開始的第一個節點,(從頭指標到該節點的所有連續的數,下同) 尾指標2——指向能滿足條件的從頭指標開始的最後一個節點 每次方案則為 21+1尾指標2-尾指標1+1

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
struct node
{
    int l,r;
}q[maxn];
long long  a[maxn],n,m,sum1[maxn],misnum,sum2[maxn];
int main()
{
    scanf("%d%d",&n,&m);
    long long cnt=m;
    for (int i=1; i<=n; i++)
      scanf("%d",&a[i]);
    for (int i=1; i<=m; i++)
      {
      scanf("%d%d",&q[i].l,&q[i].r);
      if (q[i].l==0) cnt--;
      }
    long long  t1=1,t2=1,ans=0;
    for (int i=1;i<=n;i++)
    {
        while(t1<i)t1++;
        while(t2<i)t2++;
        if(i>1){
            if (sum1[a[i-1]]==q[a[i-1]].l) cnt++;
            sum1[a[i-1]]--;
            sum2[a[i-1]]--;
        }
        while(t2<=n&&sum2[a[t2]]<q[a[t2]].r){
            sum2[a[t2]]++;
            t2++;
        }
        while(t1<=n&&cnt){
            if (sum1[a[t1]]==q[a[t1]].l-1)cnt--;
            sum1[a[t1]]++;
            t1++;
        }
        if (t1<=t2&&cnt==0){
            ans+=t2-t1+1;
        }
    }
    cout<<ans;
}

T3 題意概括:有一棵樹,S,P,Q三個點,時刻一S走一步,P,Q不動,時刻二三PQ各走兩步,S不動,求PQ追上的S的最短時刻

明顯是從s開始做。 然後每次往下走,如果兒子不是p或q的父親,那麼就可以直接算。 或者可以待在原地不動(直接算出答案)。 算的時候,畫個圖,推一推就好了。

#include<bits/stdc++.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define rep(i,a) for(i=first[a];i;i=nxt[i])
using namespace std;
const int maxn=200007;
int i,j,k,l,t,n,m,ans,s,p,q,pp,qq,ppp,qqq;
int first[maxn*2],nxt[maxn*2],head[maxn*2],num;
int f[maxn],deep[maxn],shen[maxn];
int vis[maxn];
void add(int x,int y){
    head[++num]=y,nxt[num]=first[x],first[x]=num;
}
void dfs(int x,int y){
    int i;f[x]=y;deep[x]=deep[y]+1;shen[x]=1;
    rep(i,x){
        if(head[i]!=y){
            dfs(head[i],x);
            shen[x]=max(shen[x],shen[head[i]]+1);
        }
    }
}
void dfs1(int x,int y,int z,int p,int q){
    int i;
    if(p<=0||q<=0){
        z+=min(p,q);
        ans=max(ans,z);
        return;
    }
    rep(i,x){
        if(head[i]!=y&&!vis[head[i]]){
            int k=min(p,q),t=shen[head[i]];
            if(k<=t)ans=max(ans,z+k*3);
            else{
                int o=z+t*3;k-=t;
                o+=(k/2)*3+(k%2)*2;
                ans=max(ans,o);
            }
        }
    }
    rep(i,x){
        if(vis[head[i]]){
            if(vis[head[i]]==ppp)dfs1(head[i],x,z+3,p-3,q-1);
            else dfs1(head[i],x,z+3,p-1,q-3);
        }
    }
    k=min(p,q);
    int o=z;
    o+=(k/2)*3+(k%2)*2;
    ans=max(ans,o);
}
int main(){
    scanf("%d%d%d%d",&n,&s,&p,&q);pp=ppp=p,qq=qqq=q;
    fo(i,1,n-1){
        scanf("%d%d",&k,&l);
        add(k,l);add(l,k);
    }
    dfs(s,0);
    while(pp)vis[pp]=p,pp=f[pp];
    while(qq)vis[qq]=q,qq=f[qq];
    dfs1(s,0,0,deep[p]-1,deep[q]-1);
    printf("%d\n",ans);
}