这个其实\(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; }