洛谷八連測2017R1
SAC E#1 - 一道中檔題 Factorial
題目背景
SOL君(爐石主播)和SOL菌(完美信息教室講師)是好朋友。
題目描述
SOL君很喜歡階乘。而SOL菌很喜歡研究進制。
這一天,SOL君跟SOL菌炫技,隨口算出了n的階乘。
SOL菌表示不服,立刻就要算這個數在k進制表示下末尾0的個數。
但是SOL菌太菜了於是請你幫忙。
輸入輸出格式
輸入格式:
本題包含多組數據。
每組輸入僅包含一行:兩個整數n,k。
輸出格式:
對於每組輸入,輸出一個整數:n!在k進制下後綴0的個數。
輸入輸出樣例
輸入樣例#1:10 40輸出樣例#1:
2
說明
對於20%的數據,n <= 1000000, k = 10
對於另外20%的數據,n <= 20, k <= 36
對於60%的數據,n <= 10^15,k <= 10^12
對於100%的數據,n <= 10^18,k <= 10^16
SAC E#1 - 一道簡單題 Sequence2
題目背景
小強和阿米巴是好朋友。
題目描述
小強喜歡數列。有一天,他心血來潮,寫下了三個長度均為n的數列。
阿米巴也很喜歡數列。但是他只喜歡其中一種,波動數列。
阿米巴把他的喜好告訴了小強。小強便打算找出這三個數列內的最長波動數列。
也就是說,如果我們將三個數列記做a[n][3],他必須要構造一個二元組序列:<p[i], q[i]>,使得對於任何 i>1 有:
p[i] > p[i-1]
若q[i] = 0,a[p[i]][q[i]] >= a[p[i-1]][q[i-1]]
若q[i] = 1,a[p[i]][q[i]] <= a[p[i-1]][q[i-1]]
若q[i] = 2,只要保持段內同向即可(就是對於連續的一段q[i]=2,要麽都有a[p[i]][q[i]] >= a[p[i-1]][q[i-1]],要麽都有a[p[i]][q[i]] <= a[p[i-1]][q[i-1]])。
小強希望這個二元組序列盡可能長。
提示:當q[i] != q[i-1]時,數列的增減性由q[i]而非q[i-1]決定。
清晰版題目描述
小強拿到一個3×n的數組,要在每一列選一個數(或者不選),滿足以下條件:
1.如果在第一行選,那它必須大於等於上一個數
2.如果在第二行選,那麽必須小於等於上一個數
3.如果在第三行選,對於連續的一段在第三行選的數,必須滿足方向相同(都小於等於上一個數或者都大於等於上一個數)
輸入輸出格式
輸入格式:
輸入包含4行。
第一行一個數n,表示數列長度。
第2、3、4行,每行n個整數,分別表示三個數列。
輸出格式:
輸出僅包含一個整數,即最長波動數列的長度。
輸入輸出樣例
輸入樣例#1:6 1 2 3 6 5 4 5 4 3 7 8 9 1 2 3 6 5 4輸出樣例#1:
6
說明
對於20%的數據,n <= 10, m <= 1000
對於60%的數據,n <= 1000, m <= 1000
對於100%的數據, n <= 100000, m <= 1000000000
其中m = max|a[i]|
樣例解釋:
取第三行1 2 3(增),然後取第1行6(增),然後取第三行5 4(減),長度為6。
E#1 - 一道大水題 Knight
題目背景
毒奶色和F91是好朋友。
題目描述
他們經常在一起玩一個遊戲,不,不是星際爭霸,是國際象棋。
毒奶色覺得F91是一只雞。他在一個n×n的棋盤上用黑色的城堡(車)、騎士(馬)、主教(象)、皇後(副)、國王(帥)、士兵(卒)擺了一個陣。
然而F91覺得毒奶色是一只雞。他發起了挑戰:他要操縱一個白色騎士,不經過任何一個棋子的攻擊範圍(F91可以連續行動,而毒奶色的棋子不會動,除非白騎士進入了對方的攻擊範圍),並擊殺毒奶色的國王(即進入黑國王所在的位置)。
請告訴F91他最少需要多少步驟來完成這一項壯舉。
註意:
1.當F91的白騎士走到毒奶色的棋子所在的格子上的時候,會擊殺(吃掉)該棋子。這個棋子也就不再對F91的白騎士有威脅了。
2.如果白騎士開場就在黑子的攻擊範圍內,則立刻被擊殺、F91立刻失敗。
3.即使白騎士在攻擊王的瞬間進入了其他棋子攻擊範圍(即其他棋子“看護”著王所在的格子),依然算F91獲勝。
攻擊範圍:
城堡:橫、豎方向所有位置,直到被一個其他棋子阻攔。
..#..
..#..
##C##
..#..
..#..
騎士:橫2豎1或者橫1豎2的所有位置(最多8個,類似日字)。
.#.#.
#...#
..K..
#...#
.#.#.
主教:斜向(45°)所有位置,直到被一個其他棋子阻攔。
#...#
.#.#.
..B..
.#.#.
#...#
皇後:城堡和主教的結合體(既能橫/豎向攻擊,也能45°角斜向攻擊,直到被其他棋子阻擋)。
#.#.#
.###.
##Q##
.###.
#.#.#
國王:身邊8連通位置的8個格子。
.....
.###.
.#X#.
.###.
.....
士兵:左下方/右下方(45°)的格子(最多2個)。
.....
.....
..P..
.#.#.
.....
其中字母表示棋子類型,參考輸入格式。
‘#’表示可攻擊範圍。
輸入輸出格式
輸入格式:
輸入包含多組數據。
每一組數據中,第一行一個整數n表示棋盤規模。
接下來n行,每行一個長度為n的字符串。描述棋盤的格局。
其中:
.表示空
O表示白騎士
C表示黑城堡
K表示黑騎士
B表示黑主教
Q表示黒皇後
X表示黑國王
P表示黑士兵
輸出格式:
對於每一個測試數據,每行輸出一個整數,表示F91的最小步數。
如果無論F91如何行動也無法擊殺黑國王,輸出-1。
輸入輸出樣例
輸入樣例#1:8 ...X.... ........ ........ ........ ........ ........ ........ ......O.輸出樣例#1:
4輸入樣例#2:
8 ......X. ........ .O...... ...P.Q.C .....B.. ........ ...K.... ........輸出樣例#2:
7
說明
輸入最多包含5組數據。
對於20%的數據,毒奶色只有國王。n <= 8。
對於30%的數據,毒奶色只有國王、騎士。n <= 8。
對於60%的數據,毒奶色只有國王、騎士、王後。n <= 50。
對於100%的數據,毒奶色可以有全套16顆棋子(2城堡,2騎士,2主教,1後,1王,8兵)。n <= 50。
溫馨提示:
時間限制可能比想象之中還要更緊一點,請註意實現細節以保證性能。
樣例2解釋:
一種可行的做法是:
......X.
.3..6...
.O5.....
4.2P.Q.C
1....B..
........
...K....
........
T1:
騙分解法:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 #define MAXN 1000005 8 #define ll long long 9 #define pii pair<int,int> 10 using namespace std; 11 int b[MAXN]; 12 int p[MAXN]; 13 ll n,k; 14 vector<int> s; 15 void solve(){ 16 memset(b,0,sizeof(b)); 17 memset(p,0,sizeof(p)); 18 s.clear(); 19 for(int j=2;j<=n;j++){ 20 int m=j; 21 int t=sqrt(m); 22 for(int i=2;i<=t;i++){ 23 while(!(m%i)){ 24 b[i]++; 25 m/=i; 26 } 27 } 28 if(m!=1){ 29 b[m]++; 30 } 31 } 32 ll t=sqrt(k); 33 for(int i=2;i<=t;i++){ 34 if(!(k%i)){ 35 s.push_back(i); 36 while(!(k%i)){ 37 p[i]++; 38 k/=i; 39 } 40 } 41 } 42 if(k!=1){ 43 s.push_back(k); 44 p[k]++; 45 } 46 int ans=0x7f7f7f7f; 47 for(int i=0;i<s.size();i++){ 48 ans=min(ans,b[s[i]]/p[s[i]]); 49 } 50 printf("%d\n",ans); 51 } 52 int main() 53 { 54 while(~scanf("%lld%lld",&n,&k)){ 55 solve(); 56 } 57 return 0; 58 }Code1-1
思路是對k進行質因數分解,然後對於k的每個因數p,計算n!中包含多少個p,即分解為n!=x*p^e的形式
e=x/p + x/p^2 + x/p^3 + ……
然後即可求解
暴力分解k:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #define ll long long 7 #define pll pair<ll,ll> 8 using namespace std; 9 ll n,k; 10 vector<pll > s; 11 ll i,cnt,ans,x,p,sum,t; 12 void solve(){ 13 s.clear(); 14 for(i=2;i*i<=k;i++){ 15 cnt=0; 16 while(!(k%i)){ 17 k/=i; 18 cnt++; 19 } 20 if(cnt){ 21 s.push_back(make_pair(i,cnt)); 22 } 23 } 24 if(k){ 25 s.push_back(make_pair(k,1)); 26 } 27 ans=0x7fffffffffffffffll; 28 for(i=0;i<s.size();i++){ 29 x=s[i].first,p=s[i].second; 30 sum=0; 31 for(t=x;t<=n;t*=x){ 32 sum+=(n/t); 33 } 34 ans=min(ans,sum/p); 35 } 36 printf("%lld\n",ans); 37 } 38 int main() 39 { 40 while(~scanf("%lld%lld",&n,&k)){ 41 solve(); 42 } 43 return 0; 44 }Code1-2
正解是用rho分解
T2:
方程如上
可以用離散化+樹狀數組或者線段樹維護,單調棧應該也可以
離散化之後的數組應該開3倍
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #define MAXN 100010 6 #define MAXM 100010*3 7 using namespace std; 8 struct Node{ 9 int Val; 10 int x,y; 11 Node(int p1=0,int p2=0,int p3=0){ 12 Val=p1,x=p2,y=p3; 13 } 14 }vs[MAXM]; 15 bool comp(const Node &p1,const Node &p2){ 16 return (p1.Val<p2.Val); 17 } 18 int a[4][MAXN]; 19 int n; 20 int top; 21 int cnt=1; 22 //query is the opposite of update 23 int max_bigger(int d[],int k){ 24 int ret=0; 25 while(k<=cnt){ 26 ret=max(d[k],ret); 27 k+=(k&-k); 28 } 29 return ret; 30 } 31 int max_fewer(int d[],int k){ 32 int ret=0; 33 while(k>0){ 34 ret=max(d[k],ret); 35 k-=(k&-k); 36 } 37 return ret; 38 } 39 void update_bigger(int d[],int k,int x){ 40 while(k>0){ 41 d[k]=max(d[k],x); 42 k-=(k&-k); 43 } 44 } 45 void update_fewer(int d[],int k,int x){ 46 while(k<=cnt){ 47 d[k]=max(d[k],x); 48 k+=(k&-k); 49 } 50 } 51 int read(){ 52 int x=0,f=1;char ch=getchar(); 53 while(ch<‘0‘||ch>‘9‘){if(‘-‘==ch)f=-1;ch=getchar();} 54 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 55 return x*f; 56 } 57 int f[MAXN],g[MAXN],h1[MAXN],h2[MAXN]; 58 int da1[MAXM],da2[MAXM]; 59 int db1[MAXM],db2[MAXM]; 60 int dc1[MAXM],dc2[MAXM]; 61 int dd1[MAXM],dd2[MAXM]; 62 int main() 63 { 64 // freopen("data.in","r",stdin); 65 // freopen("my.out","w",stdout); 66 n=read(); 67 for(int j=1;j<=3;j++){ 68 for(int i=1;i<=n;i++){ 69 a[j][i]=read(); 70 vs[++top]=Node(a[j][i],j,i); 71 } 72 } 73 sort(vs+1,vs+top+1,comp); 74 for(int i=1;i<=top;i++){ 75 if(vs[i].Val!=vs[i-1].Val){ 76 cnt++; 77 } 78 a[vs[i].x][vs[i].y]=cnt; 79 } 80 for(int i=1;i<=n;i++){ 81 int t=0; 82 t=max(t,max_fewer(da1,a[1][i])); 83 t=max(t,max_fewer(db1,a[1][i])); 84 t=max(t,max_fewer(dc1,a[1][i])); 85 t=max(t,max_fewer(dd1,a[1][i])); 86 f[i]=t+1; 87 t=0; 88 t=max(t,max_bigger(da2,a[2][i])); 89 t=max(t,max_bigger(db2,a[2][i])); 90 t=max(t,max_bigger(dc2,a[2][i])); 91 t=max(t,max_bigger(dd2,a[2][i])); 92 g[i]=t+1; 93 t=0; 94 t=max(t,max_fewer(da1,a[3][i])); 95 t=max(t,max_fewer(db1,a[3][i])); 96 t=max(t,max_fewer(dc1,a[3][i])); 97 h1[i]=t+1; 98 t=0; 99 t=max(t,max_bigger(da2,a[3][i])); 100 t=max(t,max_bigger(db2,a[3][i])); 101 t=max(t,max_bigger(dd2,a[3][i])); 102 h2[i]=t+1; 103 update_fewer(da1,a[1][i],f[i]); 104 update_fewer(db1,a[2][i],g[i]); 105 update_fewer(dc1,a[3][i],h1[i]); 106 update_fewer(dd1,a[3][i],h2[i]); 107 update_bigger(da2,a[1][i],f[i]); 108 update_bigger(db2,a[2][i],g[i]); 109 update_bigger(dc2,a[3][i],h1[i]); 110 update_bigger(dd2,a[3][i],h2[i]); 111 } 112 int m=0; 113 for(int i=1;i<=n;i++){ 114 m=max(max(f[i],g[i]),max(h1[i],h2[i])); 115 } 116 printf("%d\n",m); 117 118 // for(int i=1;i<=n;i++){ 119 // printf("%d ",f[i]); 120 // } 121 // printf("\n"); 122 // for(int i=1;i<=n;i++){ 123 // printf("%d ",g[i]); 124 // } 125 // printf("\n"); 126 // for(int i=1;i<=n;i++){ 127 // printf("%d ",h2[i]); 128 // } 129 // printf("\n"); 130 // for(int i=1;i<=n;i++){ 131 // printf("%d ",h1[i]); 132 // } 133 // printf("\n"); 134 return 0; 135 }Code2
洛谷八連測2017R1