【CodeForces - 357D】Xenia and Hamming (字符串问题,数论,思维)
題干:
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?%I64d?specifier.
Examples
Input
100 10 a aaaaaaaaaaOutput
0Input
1 1 abacaba abzczzzOutput
4Input
2 3 rzr azOutput
5Note
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.
題目大意:
給出一個n,m 然后給出兩個串的循環節S和T(不一定等長),?n代表第一個串有多少次循環,m代表第二個串有多少次循環,問兩個串的Hamming distance是多少,這個距離是指對應位置的字符如果相等對結果的貢獻就是0,否者就是1。(加長的兩個字符串等長)
解題報告:
? ?這是一道關于漢明距離的題目。首先漲一波知識:
這題第一眼應該就跟數論gcd,lcm相關(因為循環節和循環次數嘛最后還等長),而且數據量就知道不可能讓你暴力,肯定是有重復計算,我們需要算那個最小的然后擴大相應的倍數。
于是首先想到只要比較了兩個串的lcm長度,再擴大相應倍數就可以,但是這樣的數據量還是會TLE,想想也知道啊,如果len1和len2互質的話,復雜度O(len1*len2),最壞為10^12。
想辦法優化:
? ? ?分析一下會發現,在上面的想法中,有一部分比較是沒有必要的,比如:
? ? ? ? ? ? ? ? ? S: ?abacdcde ? ? ? ? ? ? ? ??T: ?acdaed
? ? S的長度為8,T的長度為6,len1與len2的gcd = 2,lcm = 24。
? ? 比較時 ? ? ? ? ? ? ? ?
? ? ? ?
? ? T開頭的a并不是和S中的每一位都能進行比較的,也就是說,在一個循環結中,可以一次性將T中的每一位與其將會與S中所對應的位置的字符都比較一下,也就是預處理出來。也不難發現,T的第一個字符,總與s[1]+k*gcd比較,第二個字符,總與s[2]+k*gcd比較...以此類推。(假設從s[1]為第一個字符而不是s[0])
設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就是答案。
傳送門
AC代碼1:(這是一個網絡的代碼,但是因為dpa數組開成了longlong,所以MLE了,下面有一個優化版本)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int qq = 1e6+10; char a[qq],b[qq]; int dpa[qq][27],dpb[qq][27]; ll gcd(ll a, ll b){return b==0?a:gcd(b, a%b); } ll lcm(ll a, ll b){return a/gcd(a, b)*b; } int main(){ll n,m;scanf("%lld%lld",&n,&m);scanf("%s%s",a,b);ll lena = strlen(a);ll lenb = strlen(b);ll g = gcd(lena, lenb); ll l = lena/g*lenb;memset(dpa, 0, sizeof(dpa));memset(dpb, 0, sizeof(dpb));for(int i=0; i<lena; ++i) dpa[i%g][a[i]-'a']++;for(int i=0; i<lenb; ++i) dpb[i%g][b[i]-'a']++;ll ans = 0;for(int i=0; i<g; ++i)for(int j=0; j<26; ++j)ans+=(ll)dpa[i][j]*dpb[i][j];ans = n*lena/l*ans; //每一個長度為l的字符串中,所含相同的字符有ans個、 // 求長度為n*lena/l 個長度為l的字符串中,所含相同字符的總數、 ans = n*lena - ans; //求反面、 然后用總長度減去相同字符的個數、 printf("%lld\n", ans);return 0; }AC代碼2:(這樣不需要二維數組,時間慢了一丟丟200+ms,但是剩下了很多空間復雜度)
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAX = 1e6 + 5; char s1[MAX],s2[MAX]; ll cnt[50]; ll Gcd(ll a,ll b) {while(a^=b^=a^=b%=a);return b; }int main() {ll n,m;cin>>n>>m;cin>>s1>>s2;ll len1 = strlen(s1);ll len2 = strlen(s2);ll gcd = Gcd(len1,len2);ll lcm = len1 * (len2 / gcd);ll l1=len1/gcd,l2=len2/gcd;ll ans = 0;for(ll i = 0; i<gcd; i++) {memset(cnt,0,sizeof cnt);for(ll j = 0; j<l1; j++) {cnt[s1[gcd*j + i]-'a'] ++;}for(ll j = 0; j<l2; j++) {ans += cnt[s2[gcd*j+i]-'a'];}}ans *=len1*n/ lcm ; // ans *= (m*gcd)/len1;ans = len1*n-ans;printf("%lld\n",ans);return 0 ;}總結:
? ?這題用的思維主要是:
? ? ? ? ? ? ? ? ? 1.求問題的反面。
? ? ? ? ? ? ? ? ? 2.cnt數組運用了桶計數的思想??臻g換時間,1e6正好也開的下(對這個數字還是不太敏感啊你、、)(不對這題好像不是那個桶計數,,,這題cnt數組就開27 就夠了)
?
總結
以上是生活随笔為你收集整理的【CodeForces - 357D】Xenia and Hamming (字符串问题,数论,思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小米12T核心参数曝光:骁龙8+、120
- 下一篇: 【CodeForces - 27E】Nu