這個其實\(10^5\)也能作。。node
就是\(dp[i]\)表示到第i位的方案數,\(sum[i]\)表示延伸到第i位以前的全部方案的數字的和,\(pre[i]\)記錄到第i位延伸已經結束了的數字的答案c++
轉移是\(dp[i] = dp[i - 1] * 2\)spa
\(sum[i] = sum[i - 1] * 10 + dp[i - 1] * (s[i] - '0')\)code
\(pre[i] = pre[i - 1] * 2 + sum[i ]\)orm
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); 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[15]; int64 dp[15],sum[15],ans,pre[15]; int N; void Solve() { scanf("%s",s + 1); dp[0] = 1; N = strlen(s + 1); for(int i = 1 ; i <= N ; ++i) { sum[i] = sum[i - 1] * 10 + (s[i] - '0') * dp[i - 1]; dp[i] = dp[i - 1] * 2; if(i != N) pre[i] = pre[i - 1] * 2 + sum[i]; else pre[N] = pre[i - 1] + sum[i]; } out(pre[N]);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
認爲一個\(3\times 3\)是中心格子八個方位加上本身,統計每一個\(3\times 3\)在中心格子統計three
發現一共有\((H-2)(W - 2)\)種,對於不爲0的中心格子只可能在黑格子附近八個方位加黑格子本身,暴力統計便可ip
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); 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 H,W,N; int a[MAXN],b[MAXN]; int64 ans[MAXN]; map<pii,int> zz; map<pii,int> cnt; int dx[9] = {-1,1,0,0,0,1,1,-1,-1}; int dy[9] = {0,0,-1,1,0,1,-1,1,-1}; void Solve() { read(H);read(W);read(N); for(int i = 1 ; i <= N ; ++i) { read(a[i]);read(b[i]); zz[mp(a[i],b[i])] = 1; } for(int i = 1 ; i <= N ; ++i) { for(int k = 0 ; k < 9 ; ++k) { int tx = a[i] + dx[k]; int ty = b[i] + dy[k]; if(tx > 1 && tx < H && ty > 1 && ty < W) { int c = 0; for(int h = 0 ; h < 9 ; ++h) { if(zz[mp(tx + dx[h],ty + dy[h])]) ++c; } cnt[mp(tx,ty)] = c; } } } ans[0] = 1LL * (H - 2) * (W - 2); for(auto t : cnt) { ans[0]--; ans[t.se]++; } for(int i = 0 ; i <= 9 ; ++i) { out(ans[i]);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
把邊建成點,一個點上連着的邊同種顏色用長度爲0的邊連到一塊兒,從每種顏色中選一個表明邊,新建一個點往上面連去是0回來是1的邊,表示花費1的代價在這個點轉移到別的顏色的邊get
而後跑dij就好了it
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 400005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); 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); } struct node { int to,next,val; }E[MAXN * 10]; int head[MAXN],sumE; int N,M,Ncnt; int c[MAXN],dis[MAXN]; vector<int> to[MAXN]; bool vis[MAXN]; priority_queue<pii > Q; void add(int u,int v,int c) { E[++sumE].to = v; E[sumE].next = head[u]; E[sumE].val = c; head[u] = sumE; } void Solve() { read(N);read(M); int q,p; Ncnt = M; for(int i = 1 ; i <= M ; ++i) { read(q);read(p);read(c[i]); to[q].pb(i);to[p].pb(i); } for(int i = 1 ; i <= N ; ++i) { sort(to[i].begin(),to[i].end(),[](int a,int b) {return c[a] < c[b];}); int nw = ++Ncnt; for(int j = 0 ; j < to[i].size() ; ++j) { int p = j; while(p < to[i].size() - 1 && c[to[i][p + 1]] == c[to[i][j]]) ++p; for(int h = j + 1 ; h <= p ; ++h) { add(to[i][j],to[i][h],0); add(to[i][h],to[i][j],0); } add(to[i][j],nw,0); add(nw,to[i][j],1); j = p; } } for(int i = 1 ; i <= Ncnt ; ++i) dis[i] = 1e9; for(auto t : to[1]) {dis[t] = 1;Q.push(mp(-1,t));} while(!Q.empty()) { pii now = Q.top();Q.pop(); if(vis[now.se]) continue; int u = now.se;vis[u] = 1; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(dis[v] > dis[u] + E[i].val) { dis[v] = dis[u] + E[i].val; Q.push(mp(-dis[v],v)); } } } int ans = 1e9; for(auto t : to[N]) ans = min(ans,dis[t]); if(ans >= 1e9) { puts("-1");return; } else {out(ans);enter;} } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
不一樣的玩家序列表明瞭不一樣的分牌方式,只不過同種玩家序列可能有不少中分牌方式,這種不一樣是輸的兩個玩家手中剩餘的牌不一樣的可能性帶來的io
因而咱們發現,A必勝的玩家序列是一個\(L >= N + 1\)的序列,其中兩頭都是a,中間有\(N - 1\)個a,和\((L - 1 - N)\)個\(b\)或\(c\),他們各自不超過本身的上限\(M\)和\(K\)
因而咱們發現若是有\(n\)個\(b\)或\(c\)
他們合法的排列是一段區間\([l,r]\)裏的\(\sum_{i = l}^{r}\binom{i}{n}\)
而i變大1時,\([l,r]\)兩個端點的變化不會超過1
發現咱們能夠利用\(n\)的\([l,r]\)的組合數的和,快速算出\(n + 1\)的\([l + 1,r+ 1]\)的組合數的和,而後咱們只須要修改左右端點不合法的狀況使區間合法便可
複雜度\(O(M+ K)\)
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 1000005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); 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 = 1000000007; int N,M,K,fac[MAXN],invfac[MAXN],pw[MAXN]; int s[MAXN]; 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; } void update(int &x,int y) { x = inc(x,y); } int C(int n,int m) { if(n < m) return 0; else 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 Solve() { read(N);read(M);read(K); fac[0] = 1; for(int i = 1 ; i <= 1000000 ; ++i) fac[i] = mul(fac[i - 1],i); invfac[1000000] = fpow(fac[1000000],MOD - 2); for(int i = 999999 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1); pw[0] = 1; for(int i = 1 ; i <= 1000000 ; ++i) pw[i] = mul(pw[i - 1],3); int l = 0,r = 0;s[0] = 1; for(int i = 1 ; i <= M + K ; ++i) { int tmp = inc(mul(s[i - 1],2),inc(C(i - 1,r + 1),MOD - C(i - 1,l))); ++r;++l; while(r + 1 <= i && r + 1 <= M) {update(tmp,C(i,r + 1));++r;} while(r > M) {update(tmp,MOD - C(i,r));--r;} while(i - l > K) {update(tmp,MOD - C(i,l));++l;} while(i - (l - 1) <= K && (l - 1) >= 0) {update(tmp,C(i,l - 1));--l;} s[i] = tmp; } int ans = 0; for(int i = 0 ; i <= M + K ; ++i) { int t = mul(C(N - 1 + i,N - 1),s[i]); t = mul(t,pw[M + K - i]); update(ans,t); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }