第一场(C待补)

2022年的暑假到了,在这里总结一下我做过的题
A. Not Sitting
这题经过思考能看出T的最好位置在四周,R想要距离近的话就要在中心,想到这思路就断了。但是我们可以倒着想,两者都是绝对聪明的所以T粉刷的位置一定是R即将坐的最佳位置,将距离加入排序即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<cctype>
#define debug(x) cout<<#x<<"="<<x<<'\n';
#define ll long long
#define eb emplace_back
#define endl '\n'
#define per(i,l,r) for(int i=l;i<=r;i++)
#define rep(i,l,r) for(int i=r;i>=l;i--)
using namespace std;
int T,n,m,k,ans;
void solve()
{
	cin>>n>>m;
	vector<int> v;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	v.push_back(max(i-1,n-i)+max(j-1,m-j));
	sort(v.begin(),v.end());
	for(auto x:v)cout<<x<<' ';
	cout<<endl; 
}
int main()
{
	cin>>T;
	while(T--)
	 solve();
}
 

B. Palindromes Coloring
首先考虑成对的字符一定能构成回文,ans记录成对的字符数,遍历后ans/m*2但是最后一些无法参与的字符可以位于中间位置,记下成对的字符中未分配的字符数和单个的字符数总和,与m比较。以此来决定答案是否+1

#include <iostream>
#include<bits/stdc++.h>
 
using namespace std;
int cnt[26];
bool cmp(int a, int b){ return a > b ;}
int main()
{
    int t;
    cin>>t;
    string s;
    while(t -- )
    {
        int n, k;
        cin>>n>>k;
        cin>>s;
        if(k == n)
        {
            cout<<1<<endl;
        }
        else {
            memset(cnt, 0, sizeof(cnt));
            for(int i = 0; i< n; i++)
            {
                cnt[s[i] - 'a']++;
            }
            int x = 0, y = 0;
 
            for(int i=0; i<26; i++)
            {
                if(cnt[i] % 2 == 1) y++;
                 x += cnt[i]/2;
            }
            int len = x / k; 
            if((x - len*k )* 2 + y  >= k) cout<<2*len+1<<endl;
            else cout<<2*len<<endl;
        }
    }
    return 0;
}
 

C. Longest Strike
这题就是将符合条件的放入vector里,之后进行排序,选取长度最大的区间,记录l和r就可以了
D. LIS or Reverse LIS?
因为要求严格单调递增,记录数量超过2的字符数,根据奇偶两边相应平分即可

#include<bits/stdc++.h>
using namespace std;
int n,m,k,T,ans,t;
void solve()
{
	ans=t=0;
	map<int,int> mp;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int x;cin>>x;
		mp[x]++;
		if(mp[x]<=2)ans++;
	}
	cout<<(ans+1)/2<<endl;
}
int main()
{
	cin>>T;
	while(T--)
	solve();
}
 

又学到一点

(ans+1)/2

似乎是上取整
E. Palindrome Basis
题目的大致意思就是给一个整数之后用非前导0的回文数表示出来。其实就是一个完全背包方案数,预处理出0只4e4的回文数,在预处理出dp数组,shurun时直接输出对应dp[n]即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<cctype>
#define ll long long
#define eb emplace_back
#define endl '\n'
#define per(i,l,r) for(int i=l;i<=r;i++)
#define rep(i,l,r) for(int i=r;i>=l;i--)
using namespace std;
const int mod=1e9+7;
int T,n,m,k,ans;
int a[40010],dp[40010],cnt;
bool check(int x)
{
	int y=0;
	for(int i=x;i;i/=10)y=y*10+i%10;
	return x==y;
}
void solve()
{
	cin>>n;
	cout<<dp[n]<<endl;
}
int main()
{
	for(int i=1;i<40001;i++)
	{
		if(check(i))a[cnt++]=i;
	}
	dp[0] = 1;
	for (int i = 0;i < cnt;i++) {
		for (int j = a[i];j <= 40000;j++) {
			dp[j] = (dp[j]+dp[j-a[i]])%mod;
		}
	}
	cin>>T;
	while(T--)
	 solve();
}
 

数字是否是回文的判断

bool check(int x)
{
	int y=0;
	for(int i=x;i;i/=10)y=y*10+i%10;
	return x==y;
}

完全背包方案数

for (int i = 0;i < cnt;i++) {
		for (int j = a[i];j <= 40000;j++) {
			dp[j] = (dp[j]+dp[j-a[i]])%mod;
		}
	}

F. Representative Edges
首先看这个公式
在这里插入图片描述
刚开始我还以为只满足方差为1,最后发现只要是等差数列都可以,仔细读题发现数组位置是不可动的(最开始读题还读错了QWQ)。数据量不大,所以只需要暴力枚举每一个方差记录下不符合的数字个数,最小的那个即为答案。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,ans,T;
double f[30010];
bool eq(double x,double y)
{
	return abs(x-y)<=1e-6;
}
void solve()
{
	ans=1e9;
	cin>>n;//cout<<n<<endl;
	for(int i=0;i<n;i++)cin>>f[i];
	if(n==1)
	{
		cout<<0<<endl;
		return ;
	}
	for(int i=0;i<n;i++)
	{
		for(int j=i+1;j<n;j++)
		{
			int res=0;
			double d=double(f[j]-f[i])/double(j-i);//cout<<d<<endl;
			for(int k=0;k<n;k++)
			{
			//	cout<<f[k]<<' '<<f[i]+(k-i)*d<<endl;
				if(!eq(f[k],f[i]+(k-i)*d))res++;
			}
			//if(i==1&&j==3)cout<<d<<' '<<ans<<endl;
			ans=min(ans,res);
		//	cout<<ans<<endl;
		}
	}
	cout<<ans<<endl;
}
signed main()
{
	cin>>T;
	while(T--)
	solve();
}

G. Price Maximization
看题意由于价值都要除以k,所以我们的任务是要保证每个重量都能转换为价值,那么什么时候是理想情况呢,就是对于每个w都是k的倍数,这样不管怎么组合都不会因产生余数而浪费。接下来在考虑,假设W1,W2那么
W 1 + W 2 = ( W 1 + W 2 ) / k + ( W 1 + W 2 ) % k = W 1 / k + W 1 % k + W 2 / k + W 2 % k ; W1+W2=(W1+W2)/k+(W1+W2)\%k=W1/k+W1\%k+W2/k+W2\%k; W1+W2=(W1+W2)/k+(W1+W2)%k=W1/k+W1%k+W2/k+W2%k;
所以不论怎么组合W%k的价值是一定会贡献的,剩下的就是余数的组合问题,将所有余数放入数字中,利用最大的于最下的组成一个包,>=k ans就加一。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[200010],k,T,n,ans;
void solve()
{
	cin>>n>>k;
	ans=0;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		ans+=a[i]/k;
		a[i]%=k;
	}
	sort(a,a+n);
	int l=0,r=n-1;
	while(l<r)
	{
		if(a[l]+a[r]>=k){
			ans++;
			l++;r--;
		}
		else l++;
	}
	cout<<ans<<endl;
}
signed main()
{
	cin>>T;
	while(T--)
	solve();
}

H. Moderate Modular Mode
n m o d x = y m o d n . nmodx=ymodn. nmodx=ymodn.
由已知上述公式可由下图表示
分由两种情况表示
当x<=y时
在这里插入图片描述
此时n=y-(y%x)/2
当x>y时
在这里插入图片描述
此时n=x+y;

#include<bits/stdc++.h>
#define int long long
using namespace std;
int k,T,n,ans;
void solve()
{
	int a,b;
	cin>>a>>b;
	if(a>b)cout<<a+b<<endl;
	else cout<<b-(b%a)/2<<endl;
}
signed main()
{
	cin>>T;
	while(T--)
	solve();
}

I. Peculiar Movie Preferences
这题的意思是给n个长度不超过3的字符串,需要你在不打乱顺序的情况下取出一些组成回文。
这题我们需要分长度讨论。首先如果有任一字符串是回文的话那就一定可以挑选出该字符串组成回文。
首先设置3个map<string,int> f2,f3,h3用于记录,h2记录长度为2的字符串,f3记录长度为3但是只取前两个字符串,h3记录长度为3的字符串
设置f记录是否能输出YES
当字符串s长度为2且判断不是回文时,在f2和h2中找是否有与反转s一样的字符,有f即为1.
当字符串s为3是,首先在h3中寻找反转的s时候有,有的话f置为1.之后找后两个字符反转后在f2中是否有,将前两个字符放入f3中,字符串s放入h3中。
最后根据f输出

#include<bits/stdc++.h>
using namespace std;
int n,T;

void solve()
{
	cin>>n;
	map<string,int> f2,f3,h3;
	bool f=0;
	for(int i=0;i<n;i++)
	{
		string s;
		cin>>s;
		string rrr =s;
	        reverse(rrr.begin(), rrr.end());
	        if (rrr == s) f = 1;
		if (s.size() == 1) {
			f = 1;
		}
	else if(s.length()==2)
		{
				string t=s;
			reverse(t.begin(),t.end());
			if(f2[t]||f3[t])f=1;
			f2[s]=1;
		}
		else
		{
		
	        
	string r=s;
			reverse(r.begin(),r.end());
			if(h3[r])f=1;
			string rr=s.substr(1,2);
			reverse(rr.begin(),rr.end());
			if(f2[rr])f=1;
			string rrr=s.substr(0,2);
			h3[s]=f3[rrr]=1;
		}
	}
	cout<<(f?"YES":"NO")<<'\n';
}
int main()
{
	cin>>T;
	while(T--)
	solve();
}

J. Cross Coloring
颜色覆盖问题,一切以最后一层为主,所以倒序遍历,未被占用的行被占用了h就加一,未被占用的行被占用了l就加一,由于一个格子有k中选项,ans乘以k,当所有行或列被占用或者遍历完q个方格停止循环输出ans

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k,q,T;
const int mod=998244353;
void solve()
{
	cin>>n>>m>>k>>q;
	//cout<<n<<m<<k<<q<<endl;
	int ans=1;
	int row[200010],col[200010];
	set<int>hh,ll;
	for(int i=0;i<q;i++)
	{
		cin>>row[i]>>col[i];
	}
	int h,l;
	for(int i=q-1;i>=0;i--)
	{
		if(h==n||l==m)break;
		bool f=0;
		if(!hh.count(row[i]))
		{
			++h;
			hh.insert(row[i]);
			f=1;
		}
		if(!ll.count(col[i]))
		{
			++l;
			ll.insert(col[i]);
			f=1;
		}
		if(f)ans=ans*k%mod;
	}
	cout<<ans<<endl;
}
signed main()
{
	cin>>T;
	while(T--)
	solve();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值