DAY 2模擬賽

DAY2 

依舊是yyx出題

依舊毒瘤


 

滯空(jump/1s/64M)

題目描述:

pyy在平面上第一象限內發現了順序n個平臺(她能夠踩在這些平臺上,但必須從第i-1號平臺跳躍至i-1號平臺),這些平臺的橫座標互異且單調遞增,從i號平臺出發依次跳躍通過2-->n號平臺不容許落地。前端

給出pyy的質量m和重力加速度g(重力沿y軸負方向),考慮理想狀況下,求pyy須要消耗的最小能量(不考慮落至平臺衝量(即落至平臺後速度爲0))(單位J)。node

                                                  

 

 

 

 

設E爲能量,m爲質量,v爲速度,x爲位移,a爲加速度,t爲時間,h爲兩個點高度差。ios

能量守恆指在本題中初始動能視爲人體能量消耗;c++

牛頓第二定律給出加速運動中,加速度與位移間關係的公式;數組

動能定理和重力勢能公式給出能量計算公式。app

                                                      

 

 

樣例輸入

3
1 1 2 2 3 3

樣例輸出

 

499122214J

                                                     

 

 

 

                                                   

 

 

 

 

一個鬼畜的物理題。。。ui

pyy在中子星上以光速跳躍???spa

我自閉了code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 998244353;
inline void rd(LL &x)
{
    x=0;int f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
LL n,m,x[2],y[2],g,ans;
LL qpow(LL a)
{
    LL res=1,k=mod-2;
    while(k)
    {
        if(k&1)res=res*a%mod;
        a=a*a%mod;
        k>>=1;
    }
    return res;
}
LL _2 = qpow(2);
void down(LL x,LL h){x%=mod;h%=mod;    ans += (x*x*m%mod)*qpow(4*h);    ans%=mod;}
void up(LL x,LL h)    {x%=mod;h%=mod;    ans += (m*h%mod) + ( (x*x*m%mod) *qpow(4*h) )%mod;    ans%=mod;}
void pi_4(LL x){x%=mod;    ans += (m*x%mod)*_2;    ans%=mod;}
void solve()
{
    scanf("%lld%lld%lld",&n,&m,&g);
    rd(x[1]);    rd(y[1]);
    for(int i=2;i<=n;i++)
    {
        rd(x[i&1]);    rd(y[i&1]);
        if(y[i&1]>y[!(i&1)])    up(x[i&1]-x[!(i&1)],y[i&1]-y[!(i&1)]);
        if(y[i&1]<y[!(i&1)])    down(x[i&1]-x[!(i&1)],y[!(i&1)]-y[i&1]);
        if(y[i&1]==y[!(i&1)])    pi_4(x[i&1]-x[!(i&1)]);
    }
    printf("%lldJ",ans*g%mod);
}
int main()
{
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    solve();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

 


 

放爆竹(bomb/1s/64M)

 

1 題目描述

 

  小明和小輝一塊兒放爆竹。blog

 

  小輝將不少地雷和春雷穿成了n串。由於地雷和春雷爆炸的聲音是不同的,因此串起來之後,爆炸的聲音也是不同的。

 

  小輝本來想讓小明告訴他,若是同時點燃n串雷,最多會有多長的時間至少有兩串雷爆炸的聲音是同樣的。

 

  可是小輝以爲這個問題真是太簡單了,因此決定問小明,若是在山谷中(有迴音)同時點燃n串雷,那最多會有多長的時間至少有兩串雷爆炸的聲音是同樣的呢?

 

  小輝認爲一枚春雷或者地雷爆炸都須要1ms,且山谷中的迴音不減弱,而且小輝給出的雷串不會是任意一個雷串的重複(無論重複的雷串是否存在,即不管如何都不會存在相似於 01010101的雷串)。

 

2 輸入

 

2.1 輸入格式

 

  第一行,一個數,表示有n串雷。

 

  接下來n行,其中第i行一個01字符串描述小輝的第i串雷,其中0表示春雷,1表示地雷。

 

 

 2.2 樣例1輸入

5
001
1000
0100
010
100

2.3 樣例2輸入

6
010
011
001
0010011
101
110

3 輸出

3.1 輸出格式

  一行,一個數表示小明給出的答案。

3.2 樣例1輸出

4

3.3 樣例2輸出

6

4 樣例解釋

4.1 樣例1解釋

  第3串雷0100爆炸後獲得的聲音串0100010001000100…

  第4串雷010爆炸後獲得聲音串010010010010010…

  兩個聲音串的前4位是同樣的,因此小輝前4ms聽到的聲音是同樣的。

 

 

                                                     

 

                                                    

 

 

                                                     

                                                     

 

 

                                                    

 

                                                            

 

 

                                                            

 

#include <bits/stdc++.h>

using std::max;
using std::strlen;

const int N=20010,Mlen=510,Node=N*Mlen*2;

int n,len[N],ans;
char s[N][Mlen];

struct Trie{
    int son[Node][2],node,app[Node],dep[Node],f[Node];
    
    void init() {
        son[0][0]=son[0][1]=0;
        app[0]=dep[0]=0;
    }
    
    int newnode(int d){
        ++node;
        son[node][0]=son[node][1]=0;
        dep[node]=d;
        app[node]=0;
        return node;
    }
    
    void insert(char *s,int len,int t) {
        int p=0,add=0;
        while (t) {
            for (int i=0;i<len && add<=1000;++i) {
                int &x=son[p][s[i]-'0'],pp=p;
                p=x?x:x=newnode(dep[p]+1); f[p]=pp;
                app[p]++; add++; 
            }
            t--;
        }
    }
    
    int FindAns() {
        int ans=0;
        for (int i=1;i<=node;++i) if (app[i]>=2) {
            ans=max(ans,dep[i]);
        }
//        for (int i=1;i<=node;++i) if (app[i]>=2 && ans==dep[i]) {
//            int p=i;
//            while (p) {
//                putchar((p==son[f[p]][1])+'0');
//                p=f[p];
//            }
//            putchar('\n');
//            break;
//        }
        return ans;
    }
    
}tr;

void Init() {
    scanf("%d",&n);
    for (int i=1;i<=n;++i) {
        scanf("%s",s[i]); len[i]=strlen(s[i]);
    }
}

void Solve() {
    tr.init();
    for (int i=1;i<=n;++i) {
        tr.insert(s[i],len[i],(1000-1)/len[i]+1);
    }
    printf("%d\n",tr.FindAns());
}

int main() {
    freopen("bomb.in","r",stdin);
    freopen("bomb.out","w",stdout);
    Init();
    Solve();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

 

以上是正解std

 

個人菜雞作法:

也是字典樹,先不考慮重複的狀況,把n個01串在字典樹上建出來,而且多記錄一個數組num表示通過某一條邊的字符串的數量

而後遍歷字典樹中num大於1的邊,每次遇到結尾的標記end就將這一個字符串從新複製一遍接在如今節點的下方

在遍歷的時候記錄數量,而後取max就好了

因爲這是有須要的時候才複製,應該會比上面的題解快一些吧rwr

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;

int n;
char s[2005][501];
int ch[20000500][5];
int end[20000050];
int num[20000050];
int cnt,id;
int ans;

inline void build(int x)
{
    int now=0;
    for(int i=0;i<strlen(s[x]);i++)
    {
        int c=s[x][i]-'0';
        if(!ch[now][c]) ch[now][c]=++cnt;
        now=ch[now][c];
        num[now]++;
    }
    end[now]=(++id);
}

void dfs(int now,int an)
{
    ans=max(ans,an);
    printf("%d ",ans); 
    if(num[now]>1&&end[now]!=0)
    {
        int noow=now;
        for(int j=0;j<strlen(s[end[now]]);j++)
        {
            int c=s[end[now]][j]-'0';
            if(!ch[noow][c]) ch[noow][c]=++cnt;
            noow=ch[noow][c];
            num[noow]++;
        }
        end[noow]=end[now];
    }
    for(int i=0;i<=1;i++)
    {
        if(num[ch[now][i]]>1)        
        {
            if(ch[now][i]==0) continue;
            else 
            {
                dfs(ch[now][i],an+1);
            }
        }
        else continue;
    }
}

int main()
{
//    freopen("bomb.in","r",stdin);
//    freopen("bomb.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s[i]);
        build(i);
    }
    num[0]=n;
    dfs(0,0);
    printf("%d\n",ans);
}

pyy整隊(queue,1s,128M)

問題描述:

  衆所周知pyy當了班長,服務於民。一天體育課,趁體育老師還沒來,pyy讓班裏n個同窗先排好隊。老師不在,同窗們開始玩起了手機。站在隊伍前端玩手機,前面的人少了,誰都頂不住。因而陸陸續續有人往隊伍最後躲去,但你們都沉迷某騙氪手遊,忘記了老師說前面位置有空缺要補齊的要求。一些同窗還時不時地低頭問向指揮隊伍的班長pyy,排在本身前面成績最好的同窗是誰,這樣本身才能問心無愧放心大膽的繼續玩手機。

  這時老師來了,同窗們在能夠忽略不計的時間內收好了手機。看着處處充滿空缺的隊伍,體育老師勃然大怒並借題發揮,以揚體育組聲威,限pyy以最快的時間整頓隊伍。因爲是體育老師,並看不出來隊伍的位置後移了,老師只關心隊伍是否整齊沒有空缺。

  老師給了pyy一次移動一名同窗的權力,所以pyy沒法使用技能「向前看齊」。pyy的哥哥強制要求你幫助pyy回答以前同窗們的問題,並告訴pyy在老師來以後,至少移動多少個同窗可使隊伍整齊。

 

輸入格式

  第一行爲兩個整數n,m(1<=n,m<=1e5),表示有n位同窗,在老師來以前進行了m次小動做。

  第二行爲n個以空格隔開的整數a1,a2,…,an(1<=ai<=1e7) ,表示初始時隊伍中第i位同窗的年級成績排名(數據保證不會有兩人成績重複)。

  接下來m行描述同窗們的行爲,每行由一個字符A或S和一個整數x∈{ai|1<=i<=n} 構成。若爲A,x,則表示年級成績排名爲x的同窗向pyy詢問本身前面成績最好的是哪位同窗;若爲M,x,則表示年級成績排名爲x的同窗此時躲到了當前隊伍的最尾端(不存在隊尾同窗躲向隊尾)。

輸出格式

前m個操做中對於每一個同窗的詢問,順序輸出所詢問同窗的年級成績排名,並以換行隔開。若詢問學生不存在則輸出-1。

最後一行輸出至少移動多少位同窗,使得隊伍整齊。

樣例輸入

4 5
23 150 37 301
A 37
M 23
M 37
A 301
A 37

樣例輸出

23
150
23
1

數據範圍

對於10%的數據 n<=10,m<=20

對於30%的數據 n<=10^3,m<=10^4

對於100%的數據  n<=10^5,m<=10^5,ai<=10^7

 

正解

離散化成績+權值線段樹維護每一個人的位置。每次移動將人的位置移動到n+k(k爲操做次數)。

注意一個細節,詢問是尋找x前面權值最小的元素,那麼須要獲取實際狀況中pre_x的權值使用鏈表模擬便可。

最後枚舉最終隊列的隊首,判斷長度爲n範圍外有多少人須要調整。(其實什麼方法均可以搞搞)

部分分

對於10%的數據:模擬

對於30%的數據: n^2暴力模擬每一個時刻的狀況

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 998244353;
inline void rd(LL &x)
{
    x=0;int f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
LL n,m,x[2],y[2],g,ans;
LL qpow(LL a)
{
    LL res=1,k=mod-2;
    while(k)
    {
        if(k&1)res=res*a%mod;
        a=a*a%mod;
        k>>=1;
    }
    return res;
}
LL _2 = qpow(2);
void down(LL x,LL h){x%=mod;h%=mod;    ans += (x*x*m%mod)*qpow(4*h);    ans%=mod;}
void up(LL x,LL h)    {x%=mod;h%=mod;    ans += (m*h%mod) + ( (x*x*m%mod) *qpow(4*h) )%mod;    ans%=mod;}
void pi_4(LL x){x%=mod;    ans += (m*x%mod)*_2;    ans%=mod;}
void solve()
{
    scanf("%lld%lld%lld",&n,&m,&g);
    rd(x[1]);    rd(y[1]);
    for(int i=2;i<=n;i++)
    {
        rd(x[i&1]);    rd(y[i&1]);
        if(y[i&1]>y[!(i&1)])    up(x[i&1]-x[!(i&1)],y[i&1]-y[!(i&1)]);
        if(y[i&1]<y[!(i&1)])    down(x[i&1]-x[!(i&1)],y[!(i&1)]-y[i&1]);
        if(y[i&1]==y[!(i&1)])    pi_4(x[i&1]-x[!(i&1)]);
    }
    printf("%lldJ",ans*g%mod);
}
int main()
{
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    solve();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
相關文章
相關標籤/搜索