從高位到低位數的第i位之前前綴都相同,第i位比當前位上的數小1的狀況下,後面都填9
枚舉一下而後計算最大的就好c++
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int64 N; int x[25],tot; int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif read(N); while(N) { x[++tot] = N % 10; N /= 10; } int ans = 0,sum = 0; for(int i = tot ; i >= 1 ; --i) { ans = max(ans,sum + x[i] - 1 + (i - 1) * 9); sum += x[i]; } ans = max(ans,sum); out(ans);enter; return 0; }
若是兩個點的話或者全部點共線的話兩個端點各是0.5
咱們給這些點求一個凸包,因爲半徑是無窮大,咱們只關心凸包上的點相鄰兩邊作垂直平分線交出來的角除以2PI的值
這個值能夠用PI減去凸包上的頂角求出來git
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 100005 #define eps 1e-8 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const db PI = acos(-1.0); int N,top; db ans[105]; bool dcmp(db a,db b) { return fabs(b - a) <= eps; } struct Point { db x,y;int id; Point(db _x = 0.0,db _y = 0.0) { x = _x;y = _y; } friend Point operator + (const Point &a,const Point &b) { return Point(a.x + b.x,a.y + b.y); } friend Point operator - (const Point &a,const Point &b) { return Point(a.x - b.x,a.y - b.y); } friend Point operator * (const Point &a,const db &d) { return Point(a.x * d,a.y * d); } friend db operator * (const Point &a,const Point &b) { return a.x * b.y - a.y * b.x; } friend db dot(const Point &a,const Point &b) { return a.x * b.x + a.y * b.y; } db norm() { return sqrt(x * x + y * y); } }P[105],sta[105]; bool cmp(Point a,Point b) { db d = (a - P[1]) * (b - P[1]); if(dcmp(d,0.0)) {return (a - P[1]).norm() < (b - P[1]).norm();} else return d > 0; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif int x,y; read(N); if(N == 1) {puts("1.0");return 0;} for(int i = 1 ; i <= N ; ++i) {read(x);read(y);P[i] = Point(x,y);P[i].id = i;} for(int i = 2 ; i <= N ; ++i) { if(P[i].x < P[1].x || (P[i].x == P[1].x && P[i].y < P[1].y)) swap(P[1],P[i]); } sort(P + 2,P + N + 1,cmp); sta[++top] = P[1]; for(int i = 2 ; i <= N ; ++i) { while(top >= 2 && (P[i] - sta[top - 1]) * (sta[top] - sta[top - 1]) >= 0.0) --top; sta[++top] = P[i]; } if(top == 2) { ans[sta[1].id] = 0.5; ans[sta[2].id] = 0.5; } else { Point a,b; sta[0] = sta[top];sta[top + 1] = sta[1]; for(int i = 1 ; i <= top ; ++i) { a = sta[i + 1] - sta[i]; b = sta[i - 1] - sta[i]; ans[sta[i].id] = (PI - acos( dot(a,b) / (a.norm() * b.norm()) ) ) / (2 * PI); } } for(int i = 1 ; i <= N ; ++i) { printf("%.10lf\n",ans[i]); } return 0; }
按理來講是能夠四個四個小塊一劃,若是多出來一行或者一列或者都多,就先貪心用<>填滿多的一個橫行,貪心用^v填滿多餘的一個縱行
可是有一個邊界狀況,就是橫行縱行都剩一個,而且填滿了,這個時候剩下了5個格子,有一個<>和一個^v沒填
用3*3舉個例子
<>^
^*v
v<>
能夠這麼填
也就是咱們必須填多餘格子的時候儘可能靠右下填四個小塊的時候儘可能靠右上,剩出一個
**
**
*
來優化
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 100005 #define eps 1e-8 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,M,A,B,S,T; char ans[1005][1005]; int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif read(N);read(M);read(A);read(B); S = N;T = M; if(N * M < (A + B) * 2) { puts("NO"); return 0; } for(int i = 1 ; i <= N ; ++i) { for(int j = 1 ; j <= M ; ++j) { ans[i][j] = '.'; } } if(M & 1) { int t = 1; while(B) { if(t + 1 > N) break; ans[t][M] = '^'; ans[t + 1][M] = 'v'; t += 2; --B; } --M; } if(N & 1) { int t = T; while(A) { if(t - 1 < 1) break; ans[N][t] = '>'; ans[N][t - 1] = '<'; t -= 2; --A; } --N; } int rem = N * M; for(int i = 1 ; i <= N ; i += 2) { for(int j = M - 1 ; j >= 1 ; j -= 2) { if(A >= 2) { A -= 2; rem -= 4; ans[i][j] = '<'; ans[i][j + 1] = '>'; ans[i + 1][j] = '<'; ans[i + 1][j + 1] = '>'; } else if(B >= 2) { B -= 2; rem -= 4; ans[i][j] = '^'; ans[i + 1][j] = 'v'; ans[i][j + 1] = '^'; ans[i + 1][j + 1] = 'v'; } } } if(!A || !B || rem >= 8) { for(int i = 1 ; i <= N ; i += 2) { for(int j = M - 1 ; j >= 1 ; j -= 2) { if(ans[i][j] != '.') continue; if(A) { --A; ans[i][j] = '<'; ans[i][j + 1] = '>'; } else if(B) { --B; ans[i][j] = '^'; ans[i + 1][j] = 'v'; } } } } else if(rem >= 4){ if(A == 1 && B == 1 && (S & 1) && (T & 1)) { --A;--B; ans[N - 1][1] = '<';ans[N - 1][2] = '>'; ans[N][1] = '^';ans[N + 1][1] = 'v'; } } if(A || B) {puts("NO");return 0;} puts("YES"); for(int i = 1 ; i <= S ; ++i) { for(int j = 1 ; j <= T ; ++j) { putchar(ans[i][j]); } enter; } return 0; }
這怎麼一道普及組題。。。
\(dp[i][j][k]\)表示區間\([i,j]\)改了\(k\)個字符
\(dp[i + 1][j][k] -> dp[i][j][k]\)
\(dp[i][j - 1][k] -> dp[i][j][k]\)
若是\(s[i] == s[j]\)
\(dp[i - 1][j + 1][k] + 2 -> dp[i][j][k]\)
若是\(s[i] != s[j]\)
\(dp[i - 1][j + 1][k] + 2 -> dp[i][j][k + 1]\)
初始化\(dp[i][i][0] = 1\)spa
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 100005 #define eps 1e-8 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } char s[305]; int K,dp[305][305][305],N; void update(int &x,int y) { x = max(x,y); } void Solve() { scanf("%s",s + 1); read(K); N = strlen(s + 1); for(int i = 1 ; i <= N ; ++i) for(int j = 0 ; j <= K ; ++j) dp[i][i][j] = 1; for(int d = 2 ; d <= N ; ++d) { for(int i = 1 ; i <= N ; ++i) { int j = i + d - 1; if(j > N) break; for(int k = 0 ; k <= K ; ++k) { if(k) update(dp[i][j][k],dp[i][j][k - 1]); update(dp[i][j][k],dp[i + 1][j][k]); update(dp[i][j][k],dp[i][j - 1][k]); if(s[i] == s[j]) update(dp[i][j][k],dp[i + 1][j - 1][k] + 2); else if(k) update(dp[i][j][k],dp[i + 1][j - 1][k - 1] + 2); } } } out(dp[1][N][K]);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
這道題的題意應該是這個序列創建出來吃的方式能夠本身定的code
咱們分析一下,顯然紅球數必須很多於藍球數
設紅球數爲\(r\),藍球數爲\(b\)
咱們每一個寵物都要分配至少一個紅球,而後咱們給\(N - 1\)個寵物都分配紅球后,剩餘的都給第一個,給了\(r - (N - 1)\)個
若是\(r - (N - 1) > b\),那麼不管怎樣紅藍的前後順序,我均可以讓全部寵物變紅,那麼方案數就是\(\binom{K}{r}\)orm
在\(r != b\)時
設\(t = r - (N - 1)\)
設紅球爲1,藍球爲-1,那麼前綴和必須大於\(-t\)
能夠這麼考慮,在\(N - 1\)只寵物沒有分配紅球時,來一個紅球就給他們吃一個,以後若是來了一個藍球,若是吃了紅球的寵物沒有吃過藍球,讓它們消耗一個藍球
假如不存在這樣的狀況,咱們就把藍球都餵給第一個,若是喂到了t個藍球,那麼我沒法使第一隻變紅了,我餵給別人的話,別人也無法變紅了,因此就轉化成了這個問題
方案數相似卡特蘭數的證實
是\(\binom{K}{r} - \binom{K}{r + t}\)rem
在\(r == b\)時
仍是相似上述狀況,我仍是選擇給剩下的\(N - 1\)只各喂一個紅球,一個藍球,給第一隻喂\(t\)個紅球和藍球
那麼我在給第一隻喂滿\(t\)個藍球以前,我必須把第一隻的\(t\)個紅球喂滿了,這就要求了這個顏色的序列的最後一個值必須是-1
咱們再考慮前\(K - 1\)個位置,我必須知足前綴和大於\(-t\),那麼答案就是\(\binom{K - 1}{r} - \binom{K - 1}{r + t}\)get
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 500005 #define eps 1e-8 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 998244353; int N,K,fac[MAXN * 2],invfac[MAXN * 2],inv[MAXN * 2]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } int C(int n,int m) { if(n < m) return 0; return mul(fac[n],mul(invfac[m],invfac[n - m])); } void update(int &x,int y) { x = inc(x,y); } void Solve() { read(N);read(K); inv[1] = 1; for(int i = 2 ; i <= 1000000 ; ++i) inv[i] = mul(inv[MOD % i],MOD - MOD / i); invfac[0] = fac[0] = 1; for(int i = 1 ; i <= 1000000 ; ++i) { fac[i] = mul(fac[i - 1],i); invfac[i] = mul(invfac[i - 1],inv[i]); } int ans = 0; for(int i = 0 ; i <= K ; ++i) { int r = i,b = K - i; if(r < b || r < N) continue; if(r - (N - 1) > b) { update(ans,C(K,r)); } else if(r == b) { int t = r - (N - 1); update(ans,inc(C(K - 1,r),MOD - C(K - 1,r + t))); } else { int t = r - (N - 1); update(ans,inc(C(K,r),MOD - C(K,r + t))); } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
考慮\(dp[i][j]\)表示\(i\)行\(j\)列方格填的方案數,多了一個限制是每行必須填一個數,因此咱們枚舉\(i\),累加進答案\(\binom{n}{i} dp[i][M]\)便可it
咱們每次考慮增長一列的方案數
\(dp[p][j]\)轉移到\(dp[p + q][j + 1]\)的方案
若是\(q\)是\(0\)的話,那麼我這一列就剩\(B\)和\(C\)填的方式,有\(\binom{p + 1}{2} + 1\)多出來的1個是什麼也不選,咱們至關於加了一行,而後在\(p + 1\)中選兩個,而後刪掉加的一行,這樣就包含進了這一列選了一個點的狀況了class
若是\(q\)不爲0
咱們考慮\(B,C\)可能不是咱們新加進去的,而是原來\(p\)行中的,咱們給\(p + q\)行首尾再加上附加的兩行,而後選擇\(q + 2\)個染黑,做爲新加入的行,方案數是\(\binom{p + q + 2}{q + 2}\)
而後把多出來的兩行刪掉便可,若是刪掉的首尾兩行都沒染黑,那麼這個染黑的序列,首尾兩個黑格子都是原來\(p\)行中的,若是首和尾都染黑了,那麼這個\(p + q\)的序列,最上和最下兩個黑格子都是新加入的\(q\)行中的,若是首行黑了尾行沒黑,那麼\(p + q\)的序列,最上的格子是\(q\)行中的,最下的格子是\(p\)行中的,另外一種狀況同理
能夠卷積優化,因此就變成\(O(nm \log n)\)的了
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 8005 #define eps 1e-8 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 998244353,MAXL = 1 << 14; int N,M,fac[MAXN * 2],invfac[MAXN * 2],inv[MAXN * 2]; int f[MAXL + 5],g[MAXL + 5],dp[2][MAXN],W[MAXL + 5]; int mul(int a,int b) { return 1LL * a * b % MOD; } int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int C(int n,int m) { if(n < m) return 0; return mul(fac[n],mul(invfac[m],invfac[n - m])); } int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } void update(int &x,int y) { x = inc(x,y); } void FFT(int *p,int L,int on) { for(int i = 1 , j = L >> 1 ; i < L - 1 ; ++i) { if(i < j) swap(p[i],p[j]); int k = L >> 1; while(j >= k) { j -= k; k >>= 1; } j += k; } for(int h = 2 ; h <= L ; h <<= 1) { int wn = W[(MAXL + on * (MAXL / h)) % MAXL]; for(int k = 0 ; k < L ; k += h) { int w = 1; for(int j = k ; j < k + h / 2 ; ++j) { int u = p[j],t = mul(w,p[j + h / 2]); p[j] = inc(u,t); p[j + h / 2] = inc(u,MOD - t); w = mul(w,wn); } } } if(on == -1) { int InvL = fpow(L,MOD - 2); for(int i = 0 ; i < L ; ++i) p[i] = mul(p[i],InvL); } } void Solve() { read(N);read(M); fac[0] = 1; for(int i = 1 ; i <= N + 10 ; ++i) fac[i] = mul(fac[i - 1],i); invfac[N + 10] = fpow(fac[N + 10],MOD - 2); for(int i = N + 9 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1); W[0] = 1;W[1] = fpow(3,(MOD - 1) / MAXL); for(int i = 2 ; i < MAXL ; ++i) W[i] = mul(W[i - 1],W[1]); int cur = 0; for(int i = 0 ; i <= N ; ++i) dp[cur][i] = 1; for(int i = 1 ; i <= N ; ++i) g[i] = invfac[i + 2]; int L = 1; while(L <= 2 * N) L <<= 1; FFT(g,L,1); for(int i = 2 ; i <= M ; ++i) { memset(dp[cur ^ 1],0,sizeof(dp[cur ^ 1])); for(int j = 0 ; j <= N ; ++j) { update(dp[cur ^ 1][j],mul(dp[cur][j],inc(C(j + 1,2),1))); } memset(f,0,sizeof(f)); for(int j = 0 ; j <= N ; ++j) f[j] = mul(dp[cur][j],invfac[j]); FFT(f,L,1); for(int j = 0 ; j < L ; ++j) f[j] = mul(f[j],g[j]); FFT(f,L,-1); for(int j = 0 ; j <= N ; ++j) { update(dp[cur ^ 1][j],mul(f[j],fac[j + 2])); } cur ^= 1; } int ans = 0; for(int i = 0 ; i <= N ; ++i) { update(ans,mul(C(N,i),dp[cur][i])); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }