每一個數減去A,而後轉移N次,每次選或不選,最後是和爲0的時候的方案數,負數能夠經過把全部數右移2500作到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 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 N,A; int x[55]; int64 dp[2][55 * 55 * 2]; int V = 2505; void Solve() { read(N);read(A); for(int i = 1 ; i <= N ; ++i) { read(x[i]); x[i] -= A; } int cur = 0; dp[cur][V] = 1; for(int i = 1 ; i <= N ; ++i) { memset(dp[cur ^ 1],0,sizeof(dp[cur ^ 1])); for(int j = 0 ; j <= 2 * V ; ++j) { if(j + x[i] >= 0) { dp[cur ^ 1][j + x[i]] += dp[cur][j]; } dp[cur ^ 1][j] += dp[cur][j]; } cur ^= 1; } out(dp[cur][V] - 1);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
小於1e6的能夠暴力,大於1e6的顯然只有兩維數git
\(N = kb + r,S = k + r\)spa
必要條件是\(N - S = k(b - 1)\)code
枚舉\(N - S\)的約數而後求出b看是否合法便可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 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); } int64 N,S,b = 1e18; bool check(int64 x) { if(N / x >= x) return false; int64 k = N / x,r = N % x; return k + r == S; } void Solve() { read(N);read(S); if(N == S) b = N + 1; if(N > S) { for(int64 i = 1 ; i <= (N - S) / i ; ++i) { if((N - S) % i == 0) { int64 t = (N - S) / i + 1; if(check(t)) b = min(t,b); int64 a = (N - S) / i; t = (N - S) / a + 1; if(check(t)) b = min(t,b); } } } for(int64 i = 2 ; i <= 1000000 ; ++i) { int64 x = N,cnt = 0; while(x) { cnt += x % i; x /= i; } if(cnt == S) {b = min(b,i);break;} } if(b == 1e18) {puts("-1");} else {out(b);enter;} } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
這個倍增一下就好\(st[i][j]\)表示從i走\(2^j\)天能到的賓館是啥it
每次查詢是log的io
#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 N,L,Q; int x[MAXN],st[MAXN][20]; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) read(x[i]); read(L);read(Q); for(int i = 1 ; i <= N ; ++i) { int t = upper_bound(x + 1,x + N + 1,x[i] + L) - x - 1; st[i][0] = t; } for(int j = 1 ; j <= 19 ; ++j) { for(int i = 1 ; i <= N ; ++i) { st[i][j] = st[st[i][j - 1]][j - 1]; } } int a,b; for(int i = 1 ; i <= Q ; ++i) { read(a);read(b); if(a > b) swap(a,b); int p = a,ans = 0; for(int j = 19 ; j >= 0 ; --j) { if(st[p][j] < b) { p = st[p][j]; ans += (1 << j); } } ++ans; out(ans);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
假如全部字母同樣,答案是\(|s|\),方案數是1class
假如最小循環節長度是\(|s|\)答案是1,方案數是1循環
剩下狀況最小答案都是2,由於必定存在一種斷開某個循環子串的中間使得兩邊都不爲循環串,當循環次數爲2的時候這個成立,當循環次數爲3以上時,若是一個循環節嘗試斷開的每一個位置兩邊都是循環串,那麼這個循環節必定能夠變小,與事實不符gc
注意判斷循環節的方式是
N % (N - next[N]) == 0 ? N - next[N] : N
也就是有些狀況下先後綴即便重合了,也可能沒有循環節
以後咱們只須要枚舉位置使得兩邊的最小循環節都是自身就行了,取模1000000007是不存在的
#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 500005 //#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[MAXN]; int N; int nxt[MAXN],suf[MAXN]; bool vis[MAXN]; int gcd(int a,int b) { return b == 0 ? a : gcd(b,a % b); } void Solve() { scanf("%s",s + 1); N = strlen(s + 1); for(int i = 2 ; i <= N ; ++i) { int p = nxt[i - 1]; while(p && s[p + 1] != s[i]) p = nxt[p]; if(s[p + 1] == s[i]) nxt[i] = p + 1; else nxt[i] = 0; } if(nxt[N] == N - 1) { out(N);enter;puts("1"); } else if(nxt[N] == 0 || N % (N - nxt[N]) != 0) { puts("1");puts("1"); } else { int cnt = 0,l = N - nxt[N]; suf[N] = N + 1; for(int i = N - 1 ; i >= 1 ; --i) { int p = suf[i + 1]; while(p <= N && s[p - 1] != s[i]) p = suf[p]; if(s[p - 1] == s[i]) suf[i] = p - 1; else suf[i] = N + 1; } for(int i = N - 1 ; i > 1 ; --i) { if(suf[i] - i < (N + 1 - i) && (N + 1 - i) % (suf[i] - i) == 0) vis[i - 1] = 1; } for(int i = 2 ; i <= N ; ++i) { if(i - nxt[i] < i && i % (i - nxt[i]) == 0) vis[i] = 1; } for(int i = 1 ; i < N ; ++i) { if(!vis[i]) ++cnt; } puts("2");out(cnt);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }