DNA Alignment CodeForces - 520C (思维+快速幂)

本文介绍了一种新的DNA序列相似性评估方法,并提供了一个具体的算法实现案例。该方法通过计算两个周期性DNA序列之间的相似度来确定它们的接近程度。

DNA Alignment

CodeForces - 520C

Vasya became interested in bioinformatics. He's going to write an article about similar cyclic DNA sequences, so he invented a new method for determining the similarity of cyclic sequences.

Let's assume that strings s and t have the same length n, then the function h(s, t) is defined as the number of positions in which the respective symbols of s and t are the same. Function h(s, t) can be used to define the function of Vasya distance ρ(s, t):

where is obtained from string s, by applying left circular shift i times. For example,
ρ("AGC", "CGT") = 
h("AGC", "CGT") + h("AGC", "GTC") + h("AGC", "TCG") + 
h("GCA", "CGT") + h("GCA", "GTC") + h("GCA", "TCG") + 
h("CAG", "CGT") + h("CAG", "GTC") + h("CAG", "TCG") = 
1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 1 = 6

Vasya found a string s of length n on the Internet. Now he wants to count how many strings t there are such that the Vasya distance from the string s attains maximum possible value. Formally speaking, t must satisfy the equation: .

Vasya could not try all possible strings to find an answer, so he needs your help. As the answer may be very large, count the number of such strings modulo 109 + 7.


Input

The first line of the input contains a single integer n (1 ≤ n ≤ 105).

The second line of the input contains a single string of length n, consisting of characters "ACGT".

Output

Print a single number — the answer modulo 109 + 7.

Examples
Input
1
C
Output
1
Input
2
AG
Output
4
Input
3
TTT
Output
1
Note

Please note that if for two distinct strings t1 and t2 values ρ(s, t1) и ρ(s, t2) are maximum among all possible t, then both strings must be taken into account in the answer even if one of them can be obtained by a circular shift of another one.

In the first sample, there is ρ("C", "C") = 1, for the remaining strings t of length 1 the value of ρ(s, t) is 0.

In the second sample, ρ("AG", "AG") = ρ("AG", "GA") = ρ("AG", "AA") = ρ("AG", "GG") = 4.

In the third sample, ρ("TTT", "TTT") = 27

题意:有一个h(s,t)函数,这个函数的函数值是字符串s和t中字符相同的位置的个数。另一个函数




其实就是二重循环内循环字符串s不变,字符串t第一个元素每次移到最后一个,然后求h(),外循环s每次首字符移到最后然后再进行内循环,求这些h()函数总和。就如题目中给的例子

ρ("AGC", "CGT") = 
h("AGC", "CGT") + h("AGC", "GTC") + h("AGC", "TCG") + 
h("GCA", "CGT") + h("GCA", "GTC") + h("GCA", "TCG") + 
h("CAG", "CGT") + h("CAG", "GTC") + h("CAG", "TCG") = 
1 + 1 + 0 + 0 + 1 + 1 + 1 + 0 + 1 = 6

题目让求有多少种t使得这个p()最大



思路:这道题一开始就被题目吓到了,一直到比赛结束也没有想到思路。搜题解发现这是一个找规律的题目,题目让求有多少种t使得这个p()最大,首先我们的任务就是要知道在知道s的情况下p()的最大值是多少

观察发现它的最大值只取决于s字符串中某个出现次数最多的字符个数,为什么这么说呢?

举个例子AAACGT这个字符串我们发现次数最多的是A,那么对于

s:A A A C G T 最大的情况一定是

t:A A A A A A 因为每一个A都可以匹配三次,那么也就是在一次内循环中(t变换时)

每个A可以匹配三次那么一次内循环h()的总和应该是3*n,假如说字符串中有别的字符,那么这个字符在t循环变换的过程中这个字符可以匹配的总次数等于这个字符在s串中的个数,一定小于出现最多的那个次数,比如有C那么t串变化一个循环,C最多可以匹配一次,小于3,那么总的也一定小于3*n;再加上外循环,其实无所谓每次都是3*n,所以是最大值3*n*n。

另外一个例子加入最多出现次数的字符有多个是什么情况呢

s:A A A C C C G T 其实可以这样想,因为这么一个字符串中字符最大出现次数是3

即使有多个出现3的,但是我们t字符串中的字符能和s匹配的字符的最大次数还是3次,不会因为有多个最大出现次数而改变,而会改变的就是我们有了更多的选择方案

为了让p()函数最大,我们就会希望每个字符的匹配次数都是最大值,也就是都是都是s串中字符出现的最大次数,那么我们只要在其中最大出现次数的字符中任选一个即可

s : A A A C C C G T

t:A C C A C A C C

t :  C C A C A A A A

t: _  _ _  _  _  _  _  _

……

所以这样每个字符的再一次变换循环中最大匹配次数都是s中字符出现次数的最大值

所以说到这里估计大家就可以看到大体思路了,每个位置我们又几个最大出现次数的字符就有几种选择x,一共n个位置,总共t可以满足最大值的种类就有x^n中

最终就转化成了求快速幂,哎感叹自己思维辣鸡啊

code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e5+10;
int n;
char s[maxn];
int vis[4];
ll q_pow(ll a, ll b){
    ll ans = 1LL;
    while(b){
        if(b & 1)
            ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
int main(){
    memset(vis,0,sizeof(vis));
    scanf("%d",&n);
    scanf("%s",s);
    for(int i = 0; i < n; i++){
        if(s[i] == 'A') vis[0]++;
        if(s[i] == 'C') vis[1]++;
        if(s[i] == 'G') vis[2]++;
        if(s[i] == 'T') vis[3]++;
    }
    int maxcnt = 0;
    int cnt = 0;
    for(int i = 0; i < 4; i++){
        maxcnt = max(maxcnt,vis[i]);
    }
    for(int i = 0; i < 4; i++){
        if(vis[i] == maxcnt) cnt++;
    }
    printf("%lld\n",q_pow((ll)cnt,(ll)n));
    return 0;
}

<think>嗯,用户想了解Linux的CMA(Contiguous Memory Allocator)的配置和参数含义,特别是提到了compatible、shared-dma-pool、reusable、size、alignment这些参数。首先,我需要回忆一下CMA的基本知识。CMA是Linux内核中的一个机制,用于分配连续的物理内存块,这对需要DMA的设备尤其重要,比如GPU或视频编解码器。 用户提到的参数看起来像是设备树(Device Tree)中的配置项,因为Linux内核通常使用设备树来描述硬件信息,包括内存区域。设备树中的节点可能会有这些属性。比如,compatible属性用来匹配驱动程序,shared-dma-pool可能表示这是一个共享的DMA内存池,reusable可能指内存是否可以重复使用,size和alignment则是大小和对齐要求。 接下来需要确认每个参数的具体含义和用法。例如,compatible属性通常用于绑定设备与驱动,可能的值如"shared-dma-pool"表示该内存池用于共享DMA缓冲区。shared-dma-pool可能是一个兼容性字符串,标识这是一个共享的DMA池。reusable可能是一个布尔属性,指示内存是否可以在不需要时被系统回收,但需要时再重新分配。size和alignment则分别指定内存区域的大小和对齐方式。 此外,用户可能还关心如何配置这些参数,例如在内核配置中启用CMA,或者在设备树中正确编写节点。需要解释每个参数的作用,以及它们如何影响CMA的行为和性能。例如,较大的size可以提供更多连续内存,但可能影响系统整体内存使用;alignment确保内存地址符合特定硬件要求。 还要注意用户提到的compatible是"shared-dma-pool",可能涉及到与DMA子系统的集成。需要确保引用的资料准确,比如内核文档或相关参考资料,可能需要查找官方文档或内核源码中的说明,确保信息的正确性。同时,用户可能需要示例配置,展示这些参数如何组合使用,以及常见问题的解决方法,比如内存不足时的处理策略。 最后,生成相关问题时要考虑用户可能的后续疑问,比如CMA与其他内存分配机制的区别,如何调试CMA配置问题,或者在不同内核版本中的配置差异。这有助于用户进一步学习和解决问题。</think>### Linux CMA(Contiguous Memory Allocator)配置及参数解析 CMA(连续内存分配器)是Linux内核中用于分配大块连续物理内存的机制,主要用于支持需要DMA(直接内存访问)的设备(如GPU、视频编解码器等)[^1]。其配置主要通过设备树(Device Tree)完成,以下是关键参数的含义及示例: --- #### **1. 核心配置参数** - **`compatible = "shared-dma-pool"`** 表示该内存池用于共享DMA缓冲区,标识CMA区域为设备间共享的DMA内存池[^1]。 - **`reusable`** 标记该内存区域在未被设备占用时可被内核用于其他用途(如页缓存),需要时再通过页面迁移回收。若无此属性,CMA区域会永久保留。 - **`size`** 指定CMA区域的大小,单位为字节。例如:`size = <0x4000000>;` 表示64MB。 - **`alignment`** 定义内存对齐要求(字节),通常与硬件限制相关。例如:`alignment = <0x200000>;` 表示2MB对齐。 - **`alloc-ranges`** 指定物理地址范围,限制CMA区域的分配位置。例如:`alloc-ranges = <0x0 0x80000000>;` 表示在0x0到0x80000000之间分配。 --- #### **2. 设备树配置示例** ```dts reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; cma_region: cma@90000000 { compatible = "shared-dma-pool"; reusable; reg = <0x0 0x90000000 0x0 0x4000000>; // 起始地址0x90000000,大小64MB alignment = <0x200000>; // 2MB对齐 }; }; ``` --- #### **3. 内核启动参数** 通过内核命令行可全局配置CMA: ```bash cma=64M@0x90000000 # 分配64MB CMA内存,起始地址0x90000000 cma=256M # 自动分配256MB CMA内存 ``` --- #### **4. 性能与调试** - **查看CMA状态** ```bash cat /proc/meminfo | grep Cma # 输出:CmaTotal: 262144 kB, CmaFree: 131072 kB ``` - **常见问题** - **分配失败**:可能因碎片化或CMA区域过小,需增大`size`或优化对齐。 - **性能下降**:启用`reusable`可能引入页面迁移开销,需权衡实时性需求。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值