2020 Hunan University Student Computer Programming Competition

  1. String Commutativity Finding the minimum cyclic node with kmp

Given n string s 1 , s 2 . . . . . . s n s_1,s_2......s_n s1, s2... sn ask how many pairs of i,j satisfy I < J, and s i + s j = s j + s i s_i+s_j=s_j+s_i si​+sj​=sj​+si​. N < = 1E5, the total length of all strings shall not exceed 5e6.

Idea: first, we have to start from s i + s j = s j + s i s_i+s_j=s_j+s_i si + sj = sj + si s i and s j s_i and s_j si , and sj , have the same minimum cycle section. After analyzing this point, it is a simple kmp to find the minimum cyclic node. For a string s, note that the length of S is len. After finding the ne array, the length of the minimum cyclic section L= len-ne[len]. If len%L=0, the string s can be exactly obtained by looping len/L times through the looping section. If len%L=0, L-ne[len]%L characters need to be added (from s 1 s_1 s1 (start...), which constitutes the character obtained by looping several times in the loop section.

The code is as follows:

#include <bits/stdc++.h>
using namespace std;
const int N=1000010, M=1e9+7;
typedef long long LL;
int n;
char s[N];
int ne[N];
string cale()
{
	int len=strlen(s+1);
	for(int i=2,j=0;i<=len;i++)
	{
		while(j&&s[i]!=s[j+1])j=ne[j];
		if(s[i]==s[j+1])j++;
		ne[i]=j;
	}
	int L=len-ne[len];
	if(len%L==0)len=L;
	string ans="";
	for(int i=1;i<=len;i++)ans+=s[i];
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>n)
	{
		map<string,int> cnt;
		LL ans=0;
		for(int i=1;i<=n;i++)
		{
			cin>>(s+1);
			string ss=cale();
			ans+=cnt[ss];
			cnt[ss]++;
		}
		cout<<ans<<"\n";
	}
	return 0;
}

Summary: KMP finds the minimum cyclic section and the minimum added characters.

  1. Absolute Difference Equation thinking

Given a sequence a of length n, it contains only 0, 1,?, Among them? Can be replaced with 0 or 1. Define absolute difference b i = ∣ a i − a i + 1 ∣ b_i=|a_i-a_{i+1}| bi = ∣ ai − ai+1 ∣, keep doing this operation, know the remaining number, and ask the scheme number that the last remaining number is 1. Mold 1e9+7

Idea: first of all, we must know the essence of subtraction absolute value operation, that is, XOR operation.

For example, observe:

a 1 , a 2 , a 3 , a 4 a_1,a_2,a_3,a_4 a1​,a2​,a3​,a4​

a 1 ⨁ a 2 , a 2 ⨁ a 3 , a 3 ⨁ a 4 a_1\bigoplus a_2,a_2\bigoplus a_3,a_3\bigoplus a_4 a1​⨁a2​,a2​⨁a3​,a3​⨁a4​

a 1 ⨁ a 2 ⨁ a 2 ⨁ a 3 , a 2 ⨁ a 3 ⨁ a 3 ⨁ a 4 a_1\bigoplus a_2\bigoplus a_2\bigoplus a_3,a_2\bigoplus a_3\bigoplus a_3\bigoplus a_4 a1​⨁a2​⨁a2​⨁a3​,a2​⨁a3​⨁a3​⨁a4​

a 1 ⨁ a 2 ⨁ a 2 ⨁ a 2 ⨁ a 3 ⨁ a 3 ⨁ a 3 ⨁ a 4 a_1\bigoplus a_2\bigoplus a_2\bigoplus a_2\bigoplus a_3\bigoplus a_3\bigoplus a_3\bigoplus a_4 a1​⨁a2​⨁a2​⨁a2​⨁a3​⨁a3​⨁a3​⨁a4​

We found a 1 , a 2 , a 3 , a 4 a_1,a_2,a_3,a_4 The number of occurrences of a1, a2, a3 and a4 , is 1, 3 and 1 respectively, which is exactly the combination number

So a_i the number of final occurrences is C ( n − 1 , i − 1 ) C(n-1,i-1) C(n−1,i−1)

According to the nature of XOR budget, only an odd number of times will have an impact on the final result.

When the number appearing in the odd position can ensure that the final result is 1, for the even part? The contribution to the final result is 2 c n t 1 2^{cnt1} 2cnt1, for the odd part 2 c n t 2 − 1 2^{cnt2-1} 2cnt2−1 . If the final result cannot be 1, the result is 0. Then there will be another problem. We can't calculate the number of combinations within the allowable time complexity. Because the parity we want to judge does not matter to the specific value. Here is a property. For C(n,k), if n & K = k, C(n,k) is odd, otherwise it is even. Then you can write.

The code is as follows:

#include <bits/stdc++.h>
using namespace std;
const int N=1000010, M=1e9+7;
typedef long long LL;
int n;
char s[N];
int qmi(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)res=(LL)res*a%M;
		a=(LL)a*a%M;
		b>>=1;
	}
	return res%M;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin>>(s+1))
	{
		n=strlen(s+1);
		int js=0,os=0,t=0;
		for(int i=1;i<=n;i++)
		{
			if((n-1&i-1)==i-1)
			{
				if(s[i]=='?')js++;
				else t^=(s[i]-'0');
			}	
			else if(s[i]=='?')os++;
		}
		int ans=0;
		if(!js)
		{
			if(t==1)ans=qmi(2,os);
		}
		else ans=qmi(2,js+os-1);
		cout<<ans<<"\n";
	}
	return 0;
}

Summary: absolute value operation can be transformed into XOR operation.

Posted by Residue on Tue, 26 Oct 2021 22:51:35 -0700