题意:给定一个n*m的矩阵,其为列递增现在变为行递增
现在给定一个数x问图一中的x在图2中是什么数字
解题思路:数学计算新生成的坐标,然后输出即可
解题代码:
#include <iostream> #include <bits/stdc++.h> #define int long long using namespace std; const int max = 2e5+10; signed main(){ int t,n,m,x; cin >> t; while(t--){ cin >> n >> m >> x; int ta,tb; ta = x % n; if(ta==0) ta =n ; tb = (x-ta)/n+1; cout << (ta-1)*m + tb <<endl; } return 0; }
题意:
给定一个由‘x’和’*‘组成的长度为n字符串,将其中的某些’*‘用’x’替代,且要求头尾的’*‘必须被替代为’x’,且两个’x’之间的距离(下标之差)不得超过给定的k
题解:电线杆问题,贪心经典,从第一个变化的符号开始取,差不超过k的都可以拿走
解题代码:
#include<bits/stdc++.h> #define int long long using namespace std; signed main(){ int t,n,k,ans,npos,fi,la; string s; cin>>t; while(t--){ cin >> n >> k; cin >> s; vector<int>vc; for(int i=0;i<s.length();i++){ if(s[i]=='*'){ vc.push_back(i); } } fi = vc[0]; la = vc.back(); if(fi==la || la-fi<=k){ if(fi==la) cout<<"1\n"; else cout<<"2\n"; continue; } ans = 2; npos = fi; while(npos+k < la){ if(s[npos+k]=='*')npos += k; else{ npos += k; while(s[npos]!='*') npos--; } ans++; } cout<<ans<<endl; } return 0; }
题意:给定两个字符串,可以删除头尾元素,问最少要惊醒多少次操作才能使的两个串相等
解题思路:最长公共子串问题,最终数出的答案为两个串的长度和减去两倍的子串长度
解题代码:
#include<bits/stdc++.h> #define int long long using namespace std; typedef long long ll; const int maxn = 120; int dp[maxn][maxn]; signed main(){ int t; cin>>t; int len1,len2,n,ans=0,tres; while(t--){ ans = tres = 0; string s1,s2; cin>>s1>>s2; len1 = s1.length(); len2 = s2.length(); memset(dp,0,sizeof dp); for(int i=0;i<len1;i++){ for(int j=0;j<len2;j++){ if(s1[i]==s2[j]) dp[i][j]=1; } } for(int i=0;i<len1;i++){ tres=0; for(int j=0;j<len2;j++){ if(dp[i+j][j]==1){ tres++; }else{ tres = 0; } ans = max(ans,tres); } } for(int i=0;i<len2;i++){ tres = 0; for(int j=0;j<len1;j++){ if(dp[j][i+j]==1){ tres++; }else{ tres = 0; } ans = max(ans,tres); } } printf("%d\n",s1.length()+s2.length()-2*ans); } return 0; }
题意:给定长度为n的数组,可以选择里面不同的两个元素删除,问最后剩下的元素最小个数是多少
题解思路:简单贪心,删除数字只与出现最多的数字的出现次数有关,如果其超过一半,那么最后他会有剩余,如果他不足,那么如果他是偶数,那么最后不会有数字剩下,如果为奇数,那么会剩下的数字为1
解题代码:
#include<bits/stdc++.h> #define int long long using namespace std; typedef long long ll; const int maxn = 120; int dp[maxn][maxn]; signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t,n; cin>>t; while(t--){ cin >> n; int tnum = -1; int tleft = 0; int tmp; vector<int>vc; map<int,int>mp; for(int i = 0;i<n;i++){ cin >> tmp; if(mp[tmp] == 0){ mp[tmp] =1; vc.push_back(tmp); }else{ mp[tmp]+=1; } } int mx = -1; for(int i = 0;i<vc.size();i++){ mx = max(mx,mp[vc[i]]); } if(mx > n-mx){ cout << mx - n + mx << endl; }else{ if(n%2)cout << 1 << endl; else cout << 0 << endl; } } return 0; }
题意:给出一个数列pi表示排列a的前i项(1<=i<=n)的最大值,要求分别求出字典序最大与最小的原排列。
解题思路:
对于字典序最小,其余位置按照剩余数字从小到大填充即可,对于字典序最大,在每一个ai未确定的位置,找出比pi小的数字中没有被使用过且最大的数字填充进去即可。
解题代码:
#include <bits/stdc++.h> #define int long long using namespace std; signed main() { ios_base::sync_with_stdio(0); cin.tie(0); int t; cin >> t; while (t--){ int n; cin >> n; vector<int> q(n); for (auto &x : q) cin >> x; set<int> nums; for (int i = 1; i <= n; i++) nums.insert(i); vector<int> per(n); per[0] = q[0]; nums.erase(q[0]); for (int i = 1; i < n; i++) if (q[i] != q[i - 1]) { per[i] = q[i]; nums.erase(q[i]); } } set<int> numssave = nums; cout << q[0] << ' '; for (int i = 1; i < n; i++) { if (per[i] == 0) { cout << *nums.begin() << ' '; nums.erase(nums.begin()); } else { cout << per[i] << ' '; } } cout << '\n'; nums = numssave; cout << q[0] << ' '; for (int i = 1; i < n; i++) { if (per[i] == 0) { auto it = --nums.lower_bound(q[i]); cout << *it << ' '; nums.erase(it); } else { cout << per[i] << ' '; } } cout << '\n'; } return 0; }