• 11.21考试总结


    T1 字符串

    题目描述

    小林与亮亮正在做一个游戏。小林随意地写出一个字符串,字符串只由大写字母组成,然后指定一个非负整数 (m),亮亮可以进行至多 (m) 次操作,每次操作为交换相邻两个字符。亮亮的目标是使得操作后的字符串出现最长相同的字符的长度最大。你能帮亮亮计算一下这个最大长度是多少吗?

    字符串长度 (Lleq 50), (0leq mleq 5000).

    solution

    我们枚举一下长度最长的是哪个字符 (S),然后在枚举这个字符 (S) 的那个位置 (T) 保持不动。剩下的与他相同的字符向他靠近,分别计算出他们与选定字符 (T) 相邻需要挪动几次,贪心的选即可。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,m,ans,num[110],pos[110][110],b[110];
    char s[110];
    inline int read()
    {
        int s = 0,w = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
        return s * w;
    }
    int calc(int x)
    {
        int res = 0;
        if(num[x] <= 1) return num[x];
        for(int i = 1; i <= num[x]; i++)
        {
            int tot = 0, now = 1;
            for(int j = 1; j <= num[x]; j++)
            {
                b[j] = abs(pos[x][i] - pos[x][j]) - abs(j - i); 
            }
            sort(b+1,b+num[x]+1);
            while(now <= num[x] && tot + b[now] <= m){ tot += b[now]; now++; }
            res = max(res,now-1);
        }
        return res;
    }
    int main()
    {
    	freopen("string.in","r",stdin);
    	freopen("string.out","w",stdout);
        scanf("%s",s+1); m = read();
        n = strlen(s+1);
        for(int i = 1; i <= n; i++)
        {
            int c = s[i] - 'A';
            pos[c][++num[c]] = i;
        }
        for(int i = 0; i <= 25; i++)
        {
            ans = max(ans,calc(i));
        }
        printf("%d
    ",ans);
        fclose(stdin); fclose(stdout);
        return 0;
    }
    
    

    T2 桃园之礼

    给你一个 $n imes m $ 的网格图,里面有 (k) 个点要经过,坐标分别为 ((x_1,y_1,x_2,y_2...x_k,y_k)) .让你求从 ((1,1)-(n,m)) 且进过所有 (k) 的点的方案数有多少个,输出答案模 (10^8) 的结果即可

    solution

    Exlucas + 中国剩余定理。

    显然每个点经过的顺序是固定的,先对 (k) 个点排一下序,就得到了这个顺序序列。

    然后问题转化为从 ((x_{i-1},y_{i-1})-(x_i,y_i)) 有多少种方案数。根据分步乘法计数原理可知把每个 (i) 的答案乘起来就是最后的答案。

    ((x_{i-1},y_{i-1})-(x_i,y_i))(C_{{x_i}-x_{i-1} + y_i-y_{i-1}}^{x_i-x_{i-1}}) 种。

    具体证明一下:问题可以分解为 在一个 (n imes m) 的矩形中,从左上角走到右下角共有几种走法。我们一共要走 (n+m-2) 步,其中向下走 (n-1) 步。这 (n-1) 步的位置可以是随意的,也就是从 (n+m-2) 步中任选 (n-1) 步向下走,方案数显然是 (C_{n+m-2}^{n-1}) .

    又因为模数不是质数,所以只能用 (Exlucas).

    emmm,(Exlucas) 的学习笔记有空再补吧。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int mod = 1e8;
    #define int long long
    int n,m,k,ans = 1;
    struct node
    {
    	int x,y;
    }e[100010];
    inline int read()
    {
        int s = 0,w = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
        return s * w;
    }
    bool comp(node a,node b)
    {
    	if(a.y == b.y) return a.x < b.x;
    	return a.y < b.y;
    }
    void exgcd(int a,int b,int &x,int &y)
    {
    	if(b == 0)
    	{
    		x = 1;
    		y = 0;
    		return;
    	}
    	exgcd(b,a%b,y,x);
    	y -= a / b * x;
    }
    int inv(int a,int b)
    {
    	int x = 0, y = 0;
    	if(!a) return 0;
    	exgcd(a,b,x,y);
    	x = (x % b + b) % b;
    	return x;
    }
    int ksm(int a,int b,int p)
    {
    	int res = 1;
    	for(; b; b >>= 1)
    	{
    		if(b & 1) res = res * a % p;
    		a = a * a % p;
    	}
    	return res;
    }
    int fac(int n,int pi,int pk)
    {
    	if(n == 0 || n == 1) return 1;
    	int ans = 1, tmp1 = 1, tmp2 = 1;
    	for(int i = 1; i <= pk; i++)
    	{
    		if(i % pi) tmp1 = tmp1 * i % pk;
    	}
    	for(int i = 1; i <= n%pk; i++)
    	{
    		if(i % pi) tmp2 = tmp2 * i % pk;
    	}
    	return fac(n/pi,pi,pk) % pk * ksm(tmp1,n/pk,pk) % pk * tmp2 % pk;
    }
    int C(int n,int m,int pi,int pk)
    {
    	int n1 = fac(n,pi,pk), m1 = fac(m,pi,pk), m2 = fac(n-m,pi,pk);
    	int x = 0, y = 0, z = 0;
    	for(int i = n; i; i /= pi) x += i/pi;
    	for(int i = m; i; i /= pi) y += i/pi;
    	for(int i = n-m; i; i /= pi) z += i/pi;
    	return n1 * inv(m1,pk) * inv(m2,pk) * ksm(pi,x-y-z,pk);
    }
    int Exlucas(int n,int m,int p)
    {
    	int P = p, ans = 0, pi, pk;
    	for(int i = 2; i <= p; i++)
    	{
    		if(p % i == 0)
    		{
    			pi = i, pk = 1;
    			while(p % i == 0) p /= i, pk *= i;
    			ans = (ans + C(n,m,pi,pk) * (P/pk) % P * inv(P/pk,pk) % P) % P; 
    		}
    	}
    	return ans;
    }
    signed main()
    {
    	freopen("peach.in","r",stdin);
    	freopen("peach.out","w",stdout);
    	n = read(); m = read(); k = read();
    	for(int i = 1; i <= k; i++)
    	{
    		e[i].x = read();
    		e[i].y = read();
    	}
    	e[k+1].x = 1; e[k+1].y = 1;
    	e[k+2].x = n; e[k+2].y = m;
    	sort(e+1,e+k+3,comp);
    	for(int i = 2; i <= k+2; i++)
    	{
    		int nn = e[i].x - e[i-1].x + 1;
    		int mm = e[i].y - e[i-1].y + 1;
    		if(nn <= 0 || m <= 0) 
    		{
    			printf("%d
    ",0);
    			return 0;
    		}
    		ans = ans * Exlucas(nn+mm-2,mm-1,mod) % mod;
    	}
    	printf("%lld
    ",ans);
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
    

    T3 魔法森林

    还没改完呢,咕咕咕。

  • 相关阅读:
    MPLS TE 配置与各大属性调整
    Net学习日记_基础提高_9
    Net学习日记_基础提高_8
    Net学习日记_基础提高_7
    Net学习日记_基础提高_6
    Net学习日记_基础提高_5
    Net学习日记_基础提高_4
    Net学习日记_基础提高_3
    Net学习日记_基础提高_2
    Net学习日记_基础提高_1
  • 原文地址:https://www.cnblogs.com/genshy/p/14034690.html
Copyright © 2020-2023  润新知