组合数学学习(一)——排列组合和母函数经典习题

B - 排列
next_permutation

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 ∼ 9 1\sim 9 19之间每次长度都加1, 10 ∼ 99 10\sim 99 1099之间每次长度都加2, 100 ∼ 999 100\sim 999 100999之间每次都加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 + m m ) {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
不能选已经选的字母,其他 n n n字母选出 m m m进行排列的方案数为 A n m A_n^m Anm
每个位置从能选的字母从大到小判断,没有则选0

int vis[20], ans[20];
ll c[20][10], fib[10];

int main()
{
    for (int i = 1; i <= 16; ++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];
        }
    }
    fib[0] = 1; for (int i = 1; i <= 7; ++i) fib[i] = fib[i - 1] * i;
    ll k;
    while (~scanf("%lld", &k)) {
        int cnt = 0;
        bool lead = true;
        for (int i = 8, j; i > 0; --i) {
            for (j = 15; j >= 1; --j) {
                if (vis[j]) continue;
                ll tmp = c[16 - cnt - 1][i - 1] * fib[i - 1];
                if (tmp < k) k -= tmp;
                else { vis[j] = true; break; }
            }
            if (!lead || j != 0) cnt++;
            if (j != 0)  lead = false;
            if (j == 0 && lead) continue;
            printf("%c", j >= 10 ? j - 10 + 'A' : j + '0');
        }
        putchar('\n');
    }
}

J - The Counting Problem
计算范围内每个数出现的个数
我们枚举每个位置,该位置把数分成三个部分,左边的数为 l e f t left left,该数字 n u m num num,右边的数为 r i g h t right right,枚举当前位置的数 i i i

c n t = { { l e f t × 1 0 l e n + r i g h t + 1 , i = = n u m l e f t × 1 0 l e n + 1 0 l e n , n u m > i , i ≠ 0 { ( l e f t − 1 ) × 1 0 l e n + r i g h t + 1 , n u m = = i ( l e f t − 1 ) × 1 0 l e n + 1 0 l e n , n u m > i , i = 0 cnt=\begin{cases}\begin{cases}left\times{10^{len}}+right+1,i==num\\left\times10^{len}+10^{len},num>i \end{cases},i\ne0\\\begin{cases}(left-1)\times10^{len}+right+1,num==i\\(left-1)\times10^{len}+10^{len},num>i \end{cases},i=0\end{cases} cnt={left×10len+right+1,i==numleft×10len+10len,num>i,i=0{(left1)×10len+right+1,num==i(left1)×10len+10len,num>i,i=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 ) = 1 S(0,0)=1 S(0,0)=1,其他全为0,因此答案要为1,就要考虑使 n = 0 , m = 0 n=0,m=0 n=0,m=0的方案数
S ( n , m ) = m S ( n − 1 , m ) + S ( n − 1 , m − 1 ) S(n,m)=mS(n-1,m)+S(n-1,m-1) S(n,m)=mS(n1,m)+S(n1,m1)分奇偶讨论

  • m为偶数时, S ( n , m ) = S ( n − 1 , m − 1 ) S(n,m)=S(n-1,m-1) S(n,m)=S(n1,m1)
  • m为奇数时, S ( n , m ) = S ( n − 1 , m ) + S ( n − 1 , m − 1 ) S(n,m)=S(n-1,m)+S(n-1,m-1) S(n,m)=S(n1,m)+S(n1,m1),代入 S ( n − 1 , m − 1 ) = S ( n − 2 , m − 2 ) S(n-1,m-1)=S(n-2,m-2) S(n1,m1)=S(n2,m2)变为奇数情况得到 S ( n , m ) = S ( n − 1 , m ) + S ( n − 2 , m − 2 ) S(n,m)=S(n-1,m)+S(n-2,m-2) S(n,m)=S(n1,m)+S(n2,m2)

n × m n\times m n×m的矩阵里,设 S ( n − 1 , m ) S(n-1,m) S(n1,m)为操作 1 1 1 S ( n − 2 , m − 2 ) S(n-2,m-2) S(n2,m2)为操作 2 2 2,因此必须有 m + 1 2 \frac{m+1}{2} 2m+1的操作 2 2 2 n − m n-m nm个操作 1 1 1,对 m + 1 2 \frac{m+1}{2} 2m+1进行插空 n − m n-m nm得到 ( m + 1 2 + n − m m + 1 2 ) {\frac{m+1}{2}+n-m\choose \frac{m+1}{2}} (2m+12m+1+nm)
( n m ) {n\choose m} (mn)判断奇偶性,处理 n , n − m , m n,n-m,m n,nm,m的2的因子数,如果因子数相减正好为0即为奇数

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;
public class Main{
	Scanner scan = new Scanner(System.in);
	BigInteger c[]=new BigInteger[110];
	BigInteger h[][] = new BigInteger[110][110];
 
	void getc(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=new PrintWriter(new OutputStreamWriter(System.out));
	void run() {
		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();
		}
	}
 
	public static void main(String[] args) {
		new Main().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 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 ( n e ) n n!\sim\frac{\sqrt{2\pi n}}{(\frac{n}{e})^n} n!(en)n2πn
即为 n ! < 2 2 i n!<2^{2^i} n!<22i,两边求对数 l o g 2 log_2 log2 1 2 l o g 2 ( 2 π n ) ⋅ n l o g 2 ( n e ) < 2 i , i ≤ 24 \frac{1}{2}log_2(2\pi n)\cdot nlog_2(\frac{n}{e})<2^i,i\le24 21log2(2πn)nlog2(en)<2i,i24,暴力求最大满足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);
	}
}

你可能感兴趣的:(刷题)