#include <bits/stdc++.h>
using namespace std;
int flag=1;
int main()
{
int T;
cin >> T;
while (T--)
{
int minn = 1e9;
int N;
cin >> N;
string s;
cin >> s;
int temp;
for (char i = 'a'; i <= 'z'; ++i)//从一头一尾开始遍历26个字母
/*
如果头尾指针相同,则向中间移动,如果不同,且有一个是当前选定字母,则该指针向中间移动,若没有当前选定字母,则continue继续选定下一字母
*/
{
temp = 1e9;
int l = 0, r = N - 1;
int num = 0;
while (l < r)
{
if (s[l] == s[r])
{
++l;
--r;
}
else
{
if (s[l] == i)
{
++l;
num++;
if(r<l||s[l]!=i&&s[l]!=s[r]){
flag=0;
break;
}
}
else if (s[r] == i)
{
--r;
num++;
if(r<l||s[r]!=i&&s[l]!=s[r]){
flag=0;
break;
}
}
else
{
flag=0;
break;
}
}
}
if(flag)
minn = min(num, minn);
flag=1;
}
if (minn == 1e9)
printf("%d\n", -1);
else
printf("%d\n", minn);
}
}
先将所有子区间i到j的乘积计算并存储,然后区间dp求出所有区间乘积差平方取最大值
#include<bits/stdc++.h>
using namespace std;
//dp[l][r]=max(dp[l][k]+dp[k+1][r]+(xl,k-xk+1,r)^2,dp[l][r])
const int mod=1000003;
long long dp[305][305];
long long s[305][305],v[305];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>v[i];
}
for(int i=1;i<=n;++i)
{
s[i][i]=1;
s[i][i-1]=1;
for(int j=i;j<=n;++j)
{
s[i][j]=(v[j]*s[i][j-1])%mod;
}
}
for(int len=2;len<=n;++len)
{
for(int i=1;i+len-1<=n;++i){
int j=i+len-1;
for(int k=i;k<j;++k)
{
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(s[i][k]-s[k+1][j])*(s[i][k]-s[k+1][j]));
}
}
}
cout<<dp[1][n]<<endl;
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2;
int flag=0;
int a[N];
int dfs(int n,int gcd) {
if(n==gcd){
flag=1;
return 1;
}
if(n%2==0){
dfs(n/2,gcd);
}
if(n%3==0){
dfs(n/3,gcd);
}
}
int main() {
int T;
cin>>T;
while(T--) {
int n;
cin>>n;
int minn=1e9+1;
int gcd1=1e9+1;
int gcd2=1e9+1;
for(int i=0; i<n; ++i) {
scanf("%d",&a[i]);
if(i>0) {
gcd1=min(gcd1,__gcd(a[i],a[i-1]));
gcd2=min(gcd1,gcd2);//用o(n)求出所有数最小公约数
}
}
for(int i=0; i<n; ++i) {
flag=0;
dfs(a[i],gcd2);//若a[i]能经过若干次除以2或除以3得到最小公约数,则符合要求
if(!flag)
{
break;
}
}
if(flag) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
flag=0;
}
}
我们只需要求出总字符串子字符串数量,选定任意字母,求出不包含该字母的所有子区间数量,剩下的就是包含该字母的区间数
#include <bits/stdc++.h>
using namespace std;
const long long N = 1e7 + 2;
long long cal(long long x)
{
return x * (x + 1) / 2;
}
int main()
{
string s;
cin >> s;
long long ans = 0;
long long sum = cal(s.length());
for (char i = 'a'; i <= 'z'; ++i)
{
if (s.find(i) == -1)
{
continue;
}
long long cnt = 0;
long long last = -1;
for (long long j = 0; j < s.length(); ++j)
{
if (i == s[j])
{
cnt += cal(j - last - 1);
last = j;
}
else if (j == s.length() - 1)
{
cnt += cal(j - last);
}
}
ans += sum - cnt;
}
cout << ans;
}
这道题的关键是选择如何快速的选择两个不同的关键字最小值,因此我们可以创建两个set容器,键为pair容器,价格和口感在两个容器分别作为第一关键字,另一个作为第二关键字,set有自动排序功能,因此在判断是否重复时可以使用lower_bound函数,在删除时,选择对应作为第一关键字容器删除头部即可,另一容器删除元素交换关键字位置就行
#include<bits/stdc++.h>
using namespace std;
struct juruo
{
int w,t;
/* data */
};
set<pair<int,int>>s1,s2;
int main()
{
int n;
cin>>n;
while(n--){
int o;
cin>>o;
int w,t;
if(o==1){
cin>>w>>t;
auto it1=s1.lower_bound({w,-1});
auto it2=s2.lower_bound({t,-1});
if(it1->first==w||it2->first==t){
continue;
}
else{
s1.insert({w,t});
s2.insert({t,w});
}
}
else if(o==2){
auto it1=s1.lower_bound({-1,-1});
s1.erase({it1->first,it1->second});
s2.erase({it1->second,it1->first});
}
else if(o==3){
auto it1=s2.lower_bound({-1,-1});
s2.erase({it1->first,it1->second});
s1.erase({it1->second,it1->first});
}
}
long long sum=0;
for(auto it=s1.begin();it!=s1.end();++it)
{
sum+=it->first;
}
cout<<sum;
}
这题只要将所有数从小到大排序,如果对任意数而言,当前数与前一个数之差小于等于k,就可以连上,就有获胜的可能
#include <bits/stdc++.h>
using namespace std;
int n, K;
int cur;
const int N = 1e5 + 2;
int a[N];
int main()
{
cin >> n >> K;
for (int i = 0; i < n; ++i)
{
cin >> a[i];
}
sort(a, a + n);
cur = 1;
for (int i = 1; i < n; ++i)
{
if (a[i]-a[i-1]<=K)
{
cur++;
}
else
{
cur = 1;
}
}
cout << cur << endl;
}
这题使用全排列函数next_permutation就能轻松过
#include <bits/stdc++.h>
using namespace std;
int p[101];
int n;
int x;
int num;
int cur = 1;
void myprint()
{
for (int i = 1; i <= num; ++i)
{
if (i == 1)
printf("%d", p[1]);
else
printf(" %d", p[i]);
}
printf("\n");
}
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> x;
for (int j = cur; j < cur + x; ++j)
{
p[j] = i;
}
cur += x;
num += x;
}
//cout << cur << endl;
do
{
myprint();
/* code */
} while (next_permutation(p + 1, p + cur));
}
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
string s;
cin >> s;
bool flag = 1;
string str = s + s;//s+s可以理解为包含循环子串总子串
for (int len = 2; len <= n; ++len)
{
for (int i = 0; i + len <= n; ++i)
{
string res = s.substr(i, len);//每次从当前位置截取一部分子串
reverse(res.begin(), res.end());//翻转子串
if (str.find(res) == str.npos)//如果在总子串无法找到翻转子串,说明不存在改子串的循环子串
{
cout << "NO" << endl;
flag = 0;
break;
}
}
if (!flag)
break;
}
if (flag)
cout << "YES" << endl;
}
}
只需要用map容器存储每一个数加上c的值,在遍历所有数,若容器存在该关键词,则ans+=mp[该数];
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
const int N = 1e5 + 2;
int a[N];
long long ans;
map<int, int>mp;
int main() {
int n, c;
cin >> n >> c;
for (int i = 0; i < n; ++i) {
cin >> a[i];
int x = a[i] + c;
mp[x]++;
}
for (int i = 0; i < n; ++i) {
if (mp[a[i]]) {
ans += mp[a[i]];
}
}
cout << ans;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 2;
int a[N], f[N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, num;
cin >> num >> n;
vector<int> v(n);
for (int i = 0; i < n; ++i)
{
cin >> v[i];
a[v[i]] = -1;
}
queue<int> que;
que.push(num);
int res = 0;
while (!que.empty() && n)
{
int len = que.size();
for (int i = 0; i < len; ++i)
{
int ans = que.front();
que.pop();
if (a[ans] == -1)
{
a[ans] = res;
--n;
}
if (ans * 3 < N && f[ans * 3] == 0)
{
que.push(ans * 3);
f[ans * 3] = 1;
}
if (ans * 2 < N && f[ans * 2] == 0)
{
que.push(ans * 2);
f[ans * 2] = 1;
}
if (ans + 1 < N && f[ans + 1] == 0)
{
que.push(ans + 1);
f[ans + 1] = 1;
}
if (ans - 1 < N && f[ans - 1] == 0)
{
que.push(ans - 1);
f[ans - 1] = 1;
}
}
res++;
}
for (auto i : v)
{
cout << a[i] << ' ';
}
}