随笔- 19  文章- 0  评论- 0  阅读- 838 

Tokitsukaze and Balance String (hard)

题目链接

题目描述🥰

题目思路😀

这道题一开始我想的是找规律进行模拟,找了一个规律但是只能过一些数据😅

正确解法应该是分类进行讨论,但是在分类讨论之前我们需要知道一些结论,我们通过观察可以发现平衡串的两个结论

  1. 首尾相同的字符串一定是平衡的
  2. 首尾不相同的字符串一定是不平衡的。

所以我们可以对首尾元素进行讨论,在讨论之前,我们需要统计字符串里面的'?'个数,记为cnt

  1. 如果首尾元素都不是'?'
    1. 如果首尾元素不相等,那么就只有首元素反转或者尾元素反转才能平衡,而总共有2^cnt个串,所以答案是2^(cnt+1)
    2. 如果首尾元素相等,那么只有首元素反转或者尾元素反转才不能平衡,总共有2^cnt个串,所以答案是2^(cnt)*(n-2)
  2. 如果首尾元素里面有一个'?'
    1. 如果将首尾中的 '?' 填成首尾相同,那么字符串中间任意翻转一个都行,这样的贡献是2^(cnt-1)*(n-2)。
    2. 如果将首尾中的 '?' 填成首尾不同,那么字符串首尾任意翻转一个都行, 这样的贡献是2^(cnt-1)*2。    
  3. 如果首尾元素都是'?'
    1. 如果将首尾中的 '?' 填成首尾相同,那么字符串中间任意翻转一个都行,这样的贡献就是2^(cnt-2)*(n-2)*2(因为两个?可以变成11或是00,所以要乘2)
    2. 如果将首尾中的 '?' 填成首尾不同,那么字符串首尾任意翻转一个都行, 这样的贡献是2^(cnt-2)*4(因为首尾的??可以是10->01,也可以是11->10,也可以是00->10,也可以是01->10,所以*4)

提醒:我们需要对于n==1的情况进行特判

  1. 如果这个是'?'的话,就输出2
  2. 如果是数字,就输出1

对于数据较大的幂次运算,应该使用快速幂,否则TLE警告🤡

AC代码🧠

// Problem: Tokitsukaze and Balance String (hard)
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/95336/C
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define dev1(a) cout << #a << '=' << a << endl;
#define dev2(a, b) cout << #a << " = " << a << "  " << #b << " = " << b << endl;
#define dev3(a, b, c) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << endl;
#define dev4(a, b, c, d) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << endl;
#define dev5(a, b, c, d, e) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << "  " << #e << " = " << e << endl;
#define vec(a)                         \
    for (int i = 0; i < a.size(); i++) \
        cout << a[i] << ' ';           \
    cout << endl;
#define darr(a, _i, _n)               \
    cout << #a << ':';                \
    for (int ij = _i; ij <= _n; ij++) \
        cout << a[ij] << ' ';         \
    cout << endl;           
#define cin(a,n)           \
     for(int i=0;i<n;i++) \
      cin>>a[i];          
#define endl "\n"
#define pow pim
int pim(int a,int k)
{
    int res=1;
    if(a==0)return 0;
    while(k) 
    {
        if(k&1)res=(int)res*a;
        k>>=1;
        a=(int)a*a;
    }
    return res;
}
#define fi first
#define se second
#define caseT \
    int T;    \
    cin >> T; \
    while (T--)
#define int long long
// #define int __int128

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;

// const int N = ;
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
 
int lcm(int a, int b)
{
    return a * b / gcd(a, b);
}
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int pow_mod(int a, int n, int m)
{
    int ans = 1;
    while(n){
        if(n&1){
            ans = (ans * a) % m;
        }
        a = (a * a) % m;
        n >>= 1;
    }
    return ans;
}
void solve()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	int cnt=0;
	for(auto x:s)if(x=='?')cnt++;
	if(s.size()==1)
    {
        if(s[0]=='?')cout<<2<<endl;
        else cout<<1<<endl;
        return;
    }
    if(s[0]!='?'&&s[n-1]!='?')
    {
        if(s[0]!=s[n-1])cout<<pow_mod(2,cnt+1,MOD)<<endl;
        else cout<<pow_mod(2,cnt,MOD)*(n-2)%MOD<<endl;
    }else{
        cout<<pow_mod(2,cnt-1,MOD)*n%MOD<<endl;
    }
}

signed main()
{

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	caseT
    solve();
    return 0;
}
/*

*/

Tokitsukaze and Concatenate‌ Palindrome

题目链接

题目描述🥰

题目思路😀

首先题目提及的可以不考虑字符串a和字符串b的排列顺序,所以我们只需要考虑字符串a和字符串b里面字符的出现次数,和开心消消乐一样的思维,用一个a里面的字符消一个b里面的字符。为了后续的讲解方便,我就把短的一个串叫做a串,长的一个串叫做b串。

解题步骤:

  1. 首先两个串进行互消,如果一个字符ch在a和b里面都有,就在a和b里面各自消去一个字符ch
  2. 其次我们可以统计a字符串里面的没有被消掉的字符个数,记作sum,因为最后要形成的是回文串,所以短的那个串里面的字符不能相互抵消,只能替换。
  3. 我们再对b字符串里面没有被消掉的字符个数进行处理,因为长的字符串内可以进行互消,所以我们统计没有被消去的字符里面出现次数为奇数的字符即可,记作ans。
  4. 对sum 和ans的大小进行判断
    1. 如果sum>=ans,就说明只能替换的字符更多,所以答案为cnt(cnt个字符都可以直接替换成和ans个字符一样的字符)
    2. 如果sum<ans,那么就先将s 抵消,再让 两两抵消,答案就是sum+floor((ans-sum)/2)

时间复杂度O(n)

AC代码🧠

// Problem: Tokitsukaze and Concatenate‌ Palindrome
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/95336/D
// Memory Limit: 512 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define dev1(a) cout << #a << '=' << a << endl;
#define dev2(a, b) cout << #a << " = " << a << "  " << #b << " = " << b << endl;
#define dev3(a, b, c) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << endl;
#define dev4(a, b, c, d) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << endl;
#define dev5(a, b, c, d, e) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << "  " << #e << " = " << e << endl;
#define vec(a)                         \
    for (int i = 0; i < a.size(); i++) \
        cout << a[i] << ' ';           \
    cout << endl;
#define darr(a, _i, _n)               \
    cout << #a << ':';                \
    for (int ij = _i; ij <= _n; ij++) \
        cout << a[ij] << ' ';         \
    cout << endl;           
#define cin(a,n)           \
     for(int i=0;i<n;i++) \
      cin>>a[i];          
#define endl "\n"
#define pow pim
int pim(int a,int k)
{
    int res=1;
    if(a==0)return 0;
    while(k) 
    {
        if(k&1)res=(int)res*a;
        k>>=1;
        a=(int)a*a;
    }
    return res;
}
#define fi first
#define se second
#define caseT \
    int T;    \
    cin >> T; \
    while (T--)
// #define int long long
// #define int __int128

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 99999999;

// const int N = ;
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
 
int lcm(int a, int b)
{
    return a * b / gcd(a, b);
}
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void solve()
{
	int n,m;
	cin>>n>>m;
	string a,b;
	cin>>a>>b;
	if(n>=m)
	{
		swap(n,m);
		swap(a,b);
	}
	    map<int,int>hash,mp;
		for(auto x:a)hash[x]++;
		for(auto x:b)mp[x]++;
		for(auto x:b){
			if(hash[x])
			{
			  hash[x]--;
			  mp[x]--;
			}
		}
		int sum=0;//记录的短的那个字符串里面不能被消去的字符个数
		for(auto x:hash)sum+=x.second;
		int ans=0;//记录的长的那个字符串里面不能被消去的字符字符
		for(auto x:mp)if(x.second&1)ans++;
		//短串里面的字符不能进行抵消,只能进行替换
		if(sum>=ans)cout<<sum<<endl;
		else cout<<sum+floor((ans-sum)/2)<<endl;
}

signed main()
{

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	caseT
    solve();
    return 0;
}
/*

*/

 

 posted on   熙玺  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

Shu-How Zの小窝

Loading...
点击右上角即可分享
微信分享提示