inline void read(int &x){int data = 0, w = 1;char ch = getchar();while(ch != '-' && !isdigit(ch))ch = getchar();if(ch == '-')w = -1, ch = getchar();while(isdigit(ch))data = 10 * data + ch - '0', ch = getchar();x = data * w;
}
void write(int x){if(x < 0)putchar('-'), x = -x;if(x > 9)write(x / 10);putchar('0' + x % 10);
}
const int maxn = 1024 + 5;
int n, m, a[maxn];int main()
{int t; read(t);while (t--) {read(n), read(m);for (int i = 1; i <= n; ++i) read(a[i]);while (m) { next_permutation(a + 1, a + n + 1); m--; }for (int i = 1; i <= n; ++i) {write(a[i]);putchar(i == n ? '\n' : ' ');}}
}
C - Round Numbers 求二進制區間內0的數量大于等于1的數量的十進制數的個數 數位dp,用一個變量保存0和1的數量差,因為中途可能出現差小于0的情況,我們加上32使其大于等于0即可
const int maxn = 32 + 5;
int dp[maxn][maxn << 1], a[maxn];
int f(int pos, int num, bool limit, bool lead) {if (pos == -1) return num >= 0;if (!limit && !lead && dp[pos][num + maxn] != -1) return dp[pos][num + maxn];int up = limit ? a[pos] : 1, sum = 0;for (int i = 0; i <= up; ++i) {if (lead && i == 0) sum += f(pos - 1, num, limit && i == a[pos], lead && i == 0);else sum += f(pos - 1, num + (i == 0 ? 1 : -1), limit && i == a[pos], lead && i == 0);}if (!limit && !lead) dp[pos][num + maxn] = sum;return sum;
}
int solve(int x) {int p = 0;while (x) {a[p++] = x % 2;x /= 2;}return f(p - 1, 0, true, true);
}
int main()
{memset(dp, -1, sizeof(dp));int a, b; read(a), read(b);write(solve(b) - solve(a - 1));
putchar('\n');
}
D - 好題 求升序并小于給出的字符串的數量 數位dp,用變量保存當前選的字符
char str[12];
ll dp[12][30];
ll f(int pos, int ch, bool limit, bool lead) {//printf("pos = %d, ch = %d, limit = %d\n", pos, ch, limit);if (pos == -1) return ch > 0;if (!limit && dp[pos][ch] != -1) return dp[pos][ch];int up = limit ? str[pos] - 'a' + 1 : 26; ll sum = 0;//printf("%d-%d\n", limit, up);for (int i = lead ? 0 : ch + 1; i <= up; ++i) {sum += f(pos - 1, i, limit && i == up, lead && i == 0);}if (!limit) dp[pos][ch] = sum;return sum;
}
int main()
{memset(dp, -1, sizeof(dp));while (~scanf("%s", &str)) {int n = strlen(str);bool flg = true;for (int i = 1; i < n; ++i) {if (str[i] <= str[i - 1]) {flg = false;break;}}if (!flg) { printf("0\n"); continue; }reverse(str, str + n);printf("%lld\n", f(n - 1, 0, true, true));}
}
E - Number Sequence 先找規律,發現1~91\sim 91~9之間每次長度都加1,10~9910\sim 9910~99之間每次長度都加2,100~999100\sim 999100~999之間每次都加3,依次類推;數的范圍從9到90到900…,公差從1到2到3…。 發現給出范圍內公差最多到5,我們暴力找到每個數在的公差的大范圍 再二分找到具體的數字
int main()
{int t; scanf("%d", &t);while (t--) {ll k; scanf("%lld", &k);int d = 0, a1 = 0, sz = 9;ll sum = 0;while (true) {d++; a1 += d;ll tmp = 1ll * a1 * sz + 1ll * sz * (sz - 1) / 2 * d;if (sum + tmp < k) {sum += tmp;a1 = a1 + (sz - 1) * d; sz *= 10;continue;}int l = 0, r = 1e6;while (l != r) {int n = (l + r) >> 1;if (1ll * a1 * n + 1ll * n * (n - 1) / 2 * d >= k - sum) r = n;else l = n + 1;}ll pre = 1ll * a1 * (l - 1) + 1ll * (l - 1) * (l - 2) / 2 * d;sum += pre;k = k - sum;int cnt = 0;for (int i = 1; ; ++i) {if (1 <= i && i <= 9) cnt++;else if (10 <= i && i <= 99) cnt += 2;else if (100 <= i && i <= 999) cnt += 3;else if (1000 <= i && i <= 9999) cnt += 4;else if (10000 <= i && i <= 99999) cnt += 5;if (cnt >= k) {cnt -= k;while (i) {if (cnt == 0) {write(i % 10); putchar('\n');break;}cnt--;i /= 10;}break;}}break;}}}
F - Paths on a Grid 經典排列組合,方案數為(n+mm){n+m\choose m}(mn+m?)
int main()
{ll n, m;while (~scanf("%lld%lld", &n, &m)) {if (n == 0 && m == 0) break;if (n > m) swap(n, m);double den = 1, mol = 1;for (ll i = m + 1; i <= n + m; ++i) {den *= 1.0 * i;mol *= 1.0 * (i - m);}printf("%.0f\n", den / mol);}
}
G - Word Index D - 好題 同一道題
char str[12];
ll dp[12][30];
ll f(int pos, int ch, bool limit, bool lead) {//printf("pos = %d, ch = %d, limit = %d\n", pos, ch, limit);if (pos == -1) return ch > 0;if (!limit && dp[pos][ch] != -1) return dp[pos][ch];int up = limit ? str[pos] - 'a' + 1 : 26; ll sum = 0;//printf("%d-%d\n", limit, up);for (int i = lead ? 0 : ch + 1; i <= up; ++i) {sum += f(pos - 1, i, limit && i == up, lead && i == 0);}if (!limit) dp[pos][ch] = sum;return sum;
}
int main()
{memset(dp, -1, sizeof(dp));while (~scanf("%s", &str)) {int n = strlen(str);bool flg = true;for (int i = 1; i < n; ++i) {if (str[i] <= str[i - 1]) {flg = false;break;}}if (!flg) { printf("0\n"); continue; }reverse(str, str + n);printf("%lld\n", f(n - 1, 0, true, true));}
}
H - The Last Non-zero Digit 求階乘的最后一位非0數 參考數學相關
int get_prime_factor(int n, int x) {if (!n) return 0;return n / x + get_prime_factor(n / x, x);
}
int g(int n, int x) {if (!n) return 0;return n / 10 + (n % 10 >= x) + g(n / 5, x);
}
int f(int n, int x) {if (!n) return 0;return f(n / 2, x) + g(n, x);
}
//2,3,7,9的循環節,其中注意若2的個數為0的話循環節第一位應該為1
int cyclic_section[][4] = {{6, 2, 4, 8}, {1, 3, 9, 7}, {1, 7, 9, 3}, {1, 9, 1, 9}};
int main() {int n, m;while (~scanf("%d%d", &n, &m)) {int cnt2 = get_prime_factor(n, 2) - get_prime_factor(n - m, 2);int cnt5 = get_prime_factor(n, 5) - get_prime_factor(n - m, 5);int cnt3 = f(n, 3) - f(n - m, 3);int cnt7 = f(n, 7) - f(n - m, 7);int cnt9 = f(n, 9) - f(n - m, 9);int ans = 1;if (cnt5 > cnt2) {printf("5\n"); continue;}if (cnt2 != cnt5) {ans *= cyclic_section[0][(cnt2 - cnt5) % 4];ans %= 10;}ans *= cyclic_section[1][cnt3 % 4]; ans %= 10;ans *= cyclic_section[2][cnt7 % 4]; ans %= 10;ans *= cyclic_section[3][cnt9 % 4]; ans %= 10;printf("%d\n", ans);}
}
I - Hexadecimal Numbers 不能選已經選的字母,其他nnn字母選出mmm進行排列的方案數為AnmA_n^mAnm? 每個位置從能選的字母從大到小判斷,沒有則選0
int ans[10];
ll fib[10];
int solve(int x, int y) {int res = 0;for (int i = 1; i <= 9; ++i) {int l = x / fib[i - 1];int r = x - l * fib[i - 1];int rt = l % 10; l /= 10;//printf("%d - %d - %d\n", l, rt, r);if (y == 0) {if (l) {res += (l - 1) * fib[i - 1];if (rt == 0) res += r + 1;else if (rt > y) res += fib[i - 1];}}else {res += l * fib[i - 1];if (rt > y) res += fib[i - 1];else if (rt == y) res += r + 1;}if (l <= 0) break;}return res;
}
int main()
{fib[0] = 1; for (int i = 1; i <= 9; ++i) fib[i] = fib[i - 1] * 10;int a, b;while (~scanf("%d%d", &a, &b)) {if (a == 0 && b == 0) break;if (a > b) swap(a, b);memset(ans, 0, sizeof(ans));for (int i = 0; i <= 9; ++i) {printf("%d%c", solve(b, i) - solve(a - 1, i), i == 9 ? '\n' : ' ');}}
}
K - How many 0’s? J的簡化版
ll fib[12];
ll solve(ll x) {if (x < 0) return -1;ll res = 0;for (int i = 1; i <= 12; ++i) {ll l = x / fib[i - 1];ll r = x - l * fib[i - 1];int rt = l % 10; l /= 10;if (!l) break;res += (l - 1) * fib[i - 1];if (rt) res += fib[i - 1];else res += r + 1;}return res;
}
int main()
{fib[0] = 1; for (int i = 1; i <= 12; ++i) fib[i] = fib[i - 1] * 10;ll a, b;while (~scanf("%lld%lld", &a, &b)) {if (a == -1 && b == -1) break;if (a == 0 && b == 0) printf("1\n");else printf("%lld\n", solve(b) - solve(a - 1));}
}
L - Binary Stirling Numbers 給出S(0,0)=1S(0,0)=1S(0,0)=1,其他全為0,因此答案要為1,就要考慮使n=0,m=0n=0,m=0n=0,m=0的方案數 S(n,m)=mS(n?1,m)+S(n?1,m?1)S(n,m)=mS(n-1,m)+S(n-1,m-1)S(n,m)=mS(n?1,m)+S(n?1,m?1)分奇偶討論
int get(int x) {int ret = 0;for (int i = 2; i <= x; i <<= 1) {ret += x / i;}return ret;
}
bool solve(int n, int m) {return get(n) - get(m) - get(n - m) == 0;
}
int main()
{int t; read(t);while (t--) {int n, m; read(n); read(m);int decre = n - m, k = (m + 1) / 2;println(solve(decre + k - 1, k - 1));}
}
M - Birthday Cake 差分和牛頓公式 參考數學相關
import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.math.BigInteger;import java.util.Scanner;publicclassMain{Scanner scan =newScanner(System.in);BigInteger c[]=newBigInteger[110];BigInteger h[][]=newBigInteger[110][110];voidgetc(BigInteger n,int m){c[1]= n;for(int i =2; i <= m+1; i++)c[i]= c[i -1].multiply(n.subtract(BigInteger.valueOf(i -1))).divide(BigInteger.valueOf(i));}PrintWriter out=newPrintWriter(newOutputStreamWriter(System.out));voidrun(){int cas=scan.nextInt();while(cas-->0){BigInteger n =scan.nextBigInteger().add(BigInteger.ONE);int m = scan.nextInt();for(int i =0; i <= m; i++)h[0][i]= BigInteger.valueOf(i).pow(m);for(int i =1; i <= m; i++)for(int j =0; j <= m - i; j++)h[i][j]= h[i -1][j +1].subtract(h[i -1][j]);BigInteger ans = BigInteger.ZERO;getc(n, m);for(int i =0; i <= m; i++)ans=ans.add(h[i][0].multiply(c[i+1]));out.println(ans);out.flush();}}publicstaticvoidmain(String[] args){newMain().run();}}
N - Sum of powers 伯努利數解決等冪求和 參考數學相關
typedef long long ll;
const int maxn = 20 + 3;
ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {ll ret = a / gcd(a, b) * b;return ret ? ret : -ret;
}
struct fraction {ll a, b;fraction() {}fraction(ll x) { a = x; b = 1; }fraction(ll x, ll y) { a = x; b = y; }void deal() {if (b < 0) b = -b, a = -a;ll k = gcd(a, b);if (k < 0) k = -k;a /= k; b /= k;}fraction operator +(const fraction& rhs) const {fraction ans;ans.b = lcm(b, rhs.b);ans.a = ans.b / b * a + ans.b / rhs.b * rhs.a;ans.deal();return ans;}fraction operator -(const fraction& rhs) const {fraction ans;ans.b = lcm(b, rhs.b);ans.a = ans.b / b * a - ans.b / rhs.b * rhs.a;ans.deal();return ans;}fraction operator *(const fraction& rhs) const {fraction ans;ans.a = a * rhs.a;ans.b = b * rhs.b;ans.deal();return ans;}fraction operator /(const fraction& rhs) const {fraction ans;ans.a = a * rhs.b;ans.b = b * rhs.a;ans.deal();return ans;}void println() {printf("%lld/%lld\n", a, b);}
};
fraction B[maxn];
ll C[maxn][maxn];
void init() {for (int i = 1; i < maxn; ++i) {C[i][0] = C[i][i] = 1;for (int j = 1; j < i; ++j) {C[i][j] = C[i - 1][j - 1] + C[i - 1][j];}}B[0] = fraction(1);for (int i = 1; i <= 20; ++i) {B[i] = fraction(0);for (int j = 0; j < i; ++j)B[i] = B[i] - fraction(C[i + 1][j]) * B[j];B[i] = B[i] / fraction(C[i + 1][i]);}
}
int n; fraction a[maxn];
int main() {init();while (~scanf("%d", &n)) {ll Lcm = 1;for (int i = 0; i <= n; ++i) {a[i] = fraction(C[n + 1][i]) * B[i] * fraction(1, n + 1);Lcm = lcm(Lcm, a[i].b);}printf("%lld ", Lcm);a[1] = a[1] + fraction(1);for (int i = 0; i <= n; ++i)printf("%lld ", Lcm / a[i].b * a[i].a);puts("0");}
}
O - Ignatius and the Princess III dfs
const int maxn = 120 + 5;
int dp[maxn][maxn];
int solve(int n, int m) {if (n == 0) return 1;if (m > n) return 0;if (dp[n][m] != -1) return dp[n][m];int res = 0;for (int i = m; i <= n; ++i) {if (n - i >= i) {res += solve(n - i, i);}else if (i == n) res += solve(0, i);}return dp[n][m] = res;
}
int main()
{memset(dp, -1, sizeof(dp));int n;while (~scanf("%d", &n)) {println(solve(n, 1));}
}
P - Train Problem II 大數+卡塔蘭數經典應用
const int maxn = 100 + 5;
struct Bigint
{vector<int> s;Bigint() { s.clear(); }Bigint operator =(int n) {while (n) {s.push_back(n % 10);n /= 10;}return *this;}friend Bigint operator *(const Bigint& a, const int& b) {Bigint res; int k = 0;for (int i = 0; i < a.s.size(); ++i) {res.s.push_back((k + a.s[i] * b) % 10);k = (k + a.s[i] * b) / 10;}while (k) {res.s.push_back(k % 10);k /= 10;}return res;}friend Bigint operator /(const Bigint& a, const int& b) {Bigint res; int k = 0;for (int i = a.s.size() - 1; i >= 0; --i) {res.s.push_back((k * 10 + a.s[i]) / b);k = (k * 10 + a.s[i]) % b;}reverse(res.s.begin(), res.s.end());while (res.s.back() == 0) res.s.pop_back();return res; }void print() {for (int i = s.size() - 1; i >= 0; --i) {putchar(s[i] + '0');}}
};
Bigint C[maxn];
int main()
{C[0] = 1;for (int i = 1; i <= 100; ++i) {C[i] = C[i - 1] * (4 * i - 2);C[i] = C[i] / (i + 1);}int n; while (~scanf("%d", &n)) {C[n].print(); putchar('\n');}
}
Q - 排列組合 指數型母函數解析
double fib(int n) {double res = 1.0;for (int i = 1; i <= n; ++i) {res = res * i;}return res;
}
double a[maxn], f[maxn], g[maxn];
int main() {int n, m;while (~scanf("%d%d", &n, &m)) {memset(f, 0, sizeof(f));memset(g, 0, sizeof(g));for (int i = 0; i < n; ++i) {scanf("%lf", &a[i]);}for (int i = 0; i <= a[0]; ++i) {f[i] = 1.0 / fib(i);}for (int i = 1; i < n; ++i) {for (int j = 0; j <= m; ++j) {for (int k = 0; k <= a[i] && j + k <= m; ++k) {g[j + k] += f[j] / fib(k);}}for (int j = 0; j <= m; ++j) {f[j] = g[j]; g[j] = 0;}}printf("%.0lf\n", f[m] * fib(m));}
}
S - Factstone Benchmark 斯特靈公式n!~2πn(ne)nn!\sim\frac{\sqrt{2\pi n}}{(\frac{n}{e})^n}n!~(en?)n2πn?? 即為n!<22in!<2^{2^i}n!<22i,兩邊求對數log2log_2log2?得12log2(2πn)?nlog2(ne)<2i,i≤24\frac{1}{2}log_2(2\pi n)\cdot nlog_2(\frac{n}{e})<2^i,i\le2421?log2?(2πn)?nlog2?(en?)<2i,i≤24,暴力求最大滿足n
typedef long long ll;
//n! = \sqrt{2\pi n}\frac{n}{e}^n
//log_2{n!} = \frac{1}{2}log_2{2\pi n}nlog_2{\frac{n}{e}}
int a[]={3,5,8,12,20,34,57,98,170,300,536,966,1754,3210,5910,10944,20366,38064,71421,134480,254016};int main(){int n;while(scanf("%d",&n),n){printf("%d\n",a[(n-1960)/10]);}return 0;
}
T - 找單詞 普通母函數解析
int a[maxn];
ll f[maxn], g[maxn];
int main()
{int t; scanf("%d", &t);while (t--) {for (int i = 1; i <= 26; ++i) scanf("%d", &a[i]);memset(f, 0, sizeof(f));memset(g, 0, sizeof(g));for (int i = 0; i <= a[1]; ++i) {f[i] = 1;}for (int i = 2; i <= 26; ++i) {for (int j = 0; j <= 50; ++j) {for (int k = 0; k <= a[i] && i * k + j <= 50; ++k) {g[i * k + j] += f[j];}}for (int j = 0; j <= 50; ++j) {f[j] = g[j]; g[j] = 0;}}ll ans = 0;for (int i = 1; i <= 50; ++i) ans += f[i];printf("%lld\n", ans);}
}