CodeForces

先上题目:

D. Xenia and Hamming
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Xenia is an amateur programmer. Today on the IT lesson she learned about the Hamming distance.

The Hamming distance between two strings s = s1s2... sn and t = t1t2... tn of equal length n is value . Record [si ≠ ti] is the Iverson notation and represents the following: if si ≠ ti, it is one, otherwise — zero.

Now Xenia wants to calculate the Hamming distance between two long strings a and b. The first string a is the concatenation of n copies of string x, that is, . The second string b is the concatenation of m copies of string y.

Help Xenia, calculate the required Hamming distance, given n, x, m, y.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 1012). The second line contains a non-empty string x. The third line contains a non-empty string y. Both strings consist of at most 106 lowercase English letters.

It is guaranteed that strings a and b that you obtain from the input have the same length.

Output

Print a single integer — the required Hamming distance.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64dspecifier.

Sample test(s)
input
100 10
a
aaaaaaaaaa
output
0
input
1 1
abacaba
abzczzz
output
4
input
2 3
rzr
az
output
5
Note

In the first test case string a is the same as string b and equals 100 letters a. As both strings are equal, the Hamming distance between them is zero.

In the second test case strings a and b differ in their 3-rd, 5-th, 6-th and 7-th characters. Thus, the Hamming distance equals 4.

In the third test case string a is rzrrzr and string b is azazaz. The strings differ in all characters apart for the second one, the Hamming distance between them equals 5.

  题意:给出两个串的循环节以及循环次数,求这两个串的汉明距离,这里的汉明距离指的是对应位置的字符如果不一样就是加1。

  这里的数据有点大,循环节的长度就有10^6,循环次数最大10^12,所以不能直接暴搜。这里的做法是先求出两个循环节的最小公倍数l和最大公约数g。然后统计面每个字符串某个位置i是哪个字符,同时保存在i%g的位置,因为在一个l的范围里面只有在g的倍数的位置两个字符串的字符才会有比较,然后统计一下l的范围里面两个字符串每一个位置的不同的字符的对数。然后因为最大公约数l的距离以后字符串的异同又会和前面一样,所以我们只要再乘以一个字符串的总长度对于l的倍数就可以了。

  但是这里需要优化,因为比较同一个位置的字符异同的时候比较次数是26*26-26如果再乘上g的话有可能会非常大,这样就会超时,所以我们需要考虑它的反面,我们可以用一个字符串的总长度剪去位置上有相同字符的数量,这样我们就可以减少一维变成g*26了。

  但是这样做可能还是会wa,因为我们还需要 注意到数据大小(10^6)*(10^12)快要到达long long 的极限了,如果我们是先用前面的到的结果ans先乘上这里的数再做后面的除法的话会有溢出的可能,所以我们需要先求了字符串的总长度对于l的倍数,然后再将ans乘以倍数,这样就不会爆long long了。

上代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define MAX 1000002
 5 #define ll long long
 6 using namespace std;
 7 
 8 char a[MAX],b[MAX];
 9 ll n,m,r,le;
10 ll la,lb,g,l,ans;
11 int dpa[MAX][26];
12 int dpb[MAX][26];
13 
14 ll gcd(ll a,ll b){
15     return b==0 ? a : gcd(b,a%b);
16 }
17 
18 
19 int main()
20 {
21     //freopen("data.txt","r",stdin);
22     while(scanf("%I64d %I64d",&n,&m)!=EOF){
23         scanf("%s",a);
24         scanf("%s",b);
25         la=strlen(a);
26         lb=strlen(b);
27         g = a>b ? gcd(la,lb) : gcd(lb,la);
28         l=la*lb/g;
29         memset(dpa,0,sizeof(dpa));
30         memset(dpb,0,sizeof(dpb));
31         for(int i=0;i<la;i++){
32             dpa[i%g][a[i]-'a']++;
33         }
34         for(int i=0;i<lb;i++){
35             dpb[i%g][b[i]-'a']++;
36         }
37         ans=0;
38         for(int i=0;i<g;i++){
39             for(int j=0;j<26;j++){
40                 ans+=(ll)dpa[i][j]*(ll)dpb[i][j];
41             }
42         }
43         ans=n*la/l*ans;
44         ans=n*la-ans;
45         printf("%I64d
",ans);
46     }
47     return 0;
48 }
/*357D*/
原文地址:https://www.cnblogs.com/sineatos/p/3908614.html