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; }
小明和小輝一塊兒放爆竹。blog
小輝將不少地雷和春雷穿成了n串。由於地雷和春雷爆炸的聲音是不同的,因此串起來之後,爆炸的聲音也是不同的。
小輝本來想讓小明告訴他,若是同時點燃n串雷,最多會有多長的時間至少有兩串雷爆炸的聲音是同樣的。
可是小輝以爲這個問題真是太簡單了,因此決定問小明,若是在山谷中(有迴音)同時點燃n串雷,那最多會有多長的時間至少有兩串雷爆炸的聲音是同樣的呢?
小輝認爲一枚春雷或者地雷爆炸都須要1ms,且山谷中的迴音不減弱,而且小輝給出的雷串不會是任意一個雷串的重複(無論重複的雷串是否存在,即不管如何都不會存在相似於 01010101的雷串)。
第一行,一個數,表示有n串雷。
接下來n行,其中第i行一個01字符串描述小輝的第i串雷,其中0表示春雷,1表示地雷。
5 001 1000 0100 010 100
6 010 011 001 0010011 101 110
一行,一個數表示小明給出的答案。
4
6
第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當了班長,服務於民。一天體育課,趁體育老師還沒來,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; }