Codeforces_356B_Xenia and Hamming(数论)

题型:数论


题意:

       汉明距离就是两个等长字符串之间的汉明距离是两个字符串对应位置的字符不同的个数,给出两个字符串S和T(不一定等长),给出求出n倍长的S和m倍长的T这两个字符串的汉明距离(加长的两个字符串等长)。


分析:

         一开始思路比较单纯,题目一看完就觉得比较出两个串的长度的最小公倍数长度的汉明距离,然后再扩大相应倍就可以了。但是这样显然是会TLE的,设S的长度为len1、T的长度为len2,如果len1和len2互质的话,复杂度就会达到O(len1*len2),最坏为10^12,过大。

         分析一下会发现,在上面的想法中,有一部分比较是没有必要的,比如:

                  S:  abacdcde                 T:  acdaed

         S的长度为8,T的长度为6,len1与len2的最小公倍数为24

         比较时                

                                                                         

          T开头的a并不是和S中的每一位都能进行比较的,也就是说,在一个循环结中,可以一次性将T中的每一位与其将会与S中所对应的位置的字符都比较一下,设g =gcd(len1,len2),设ans为S和T中对应位置相同的字符的数目,方法就是在i from 0 to gcd(len1,len2)-1 的循环中,将S分为g个小段,每段长度为len1/g,统计每次该小段上第i个字符出现的次数,然后将T中g个小段的第i个字符出现的次数加入到ans中。最后将ans扩大相应倍数,然后再用总的长度减去ans就是答案。


代码:

#include
#include
#include
#include
#include
#define MAXN 1000010
using namespace std;
char s[MAXN],t[MAXN];

__int64 gcd(__int64 x, __int64 y){
 if (!x || !y) return x > y ? x : y;
 for (__int64 t; t = x % y; x = y, y = t);
 return y;
}

int main(){
    __int64 n,m;
    while(~scanf("%I64d%I64d",&n,&m)){
        scanf("%s%s",s,t);
        __int64 l1=strlen(s);
        __int64 l2=strlen(t);
        __int64 g=gcd(l1,l2);
        __int64 ans=0;

        for(int i=0;i


你可能感兴趣的:(ACM)