中国矿业大学2021学年算法设计与分析实验课OJ2

129 阅读6分钟

1.Contest2425 - 毕老师算法实验一

传送门在这里 题目总览:

A.排列问题

 // 排列问题
 // 输入一个可能含有重复字符的字符串,打印出该字符串中所有字符的全排列。
 #include<bits/stdc++.h>
 using namespace std;
 bool IsSwap(vector<char> &chars, int nBegin, int nEnd)
 {
     for(int i=nBegin; i<nEnd; i++)  //记住是<nEnd
     {
         if(chars[i] == chars[nEnd]) return false;
     }
     return true;
 }
 void Perm(vector<char> &chars, int k, int m)
 {
     if(k==m) 
     {
         for(const char x:chars) 
         {
             cout<<x;
         }
         cout<<endl;
     }
     else
     {
         for(int i=k; i<=m; i++)
         {
             if(IsSwap(chars, k, i))
             {
                 swap(chars[k], chars[i]);
                 Perm(chars, k+1, m);
                 swap(chars[k], chars[i]);
             }
         }
     }
 }
 void Foo(vector<char> &chars)
 {
     Perm(chars, 0, chars.size()-1);
 }
 // 字符串
 bool IsSwap(string str, int nBegin, int nEnd)
 {
     for(int i=nBegin; i<nEnd; i++)  //记住是<nEnd
     {
         if(str[i] == str[nEnd]) return false;
     }
     return true;
 }
 void Perm2(string str, int k, int m)
 {
     if(k==m) 
     {
         cout<<str;
         cout<<endl;
     }
     else
     {
         for(int i=k; i<=m; i++)
         {
             if(IsSwap(str, k, i))
             {
                 swap(str[k], str[i]);
                 Perm2(str, k+1, m);
                 swap(str[k], str[i]);
             }
         }
     }
 }
 void Foo2(string str)
 {
     str.pop_back();
     cout<<str<<endl;
     Perm2(str, 0, str.length()-1);
 }
 int main()
 {
     // vector<char> chars;
     // int n;
     // cin>>n;
     // char ele;
     // for(int i=0; i<n; i++) 
     // {
     //     cin>>ele;
     //     chars.push_back(ele);
     // }
     // // for(const char x:chars) cout<<x;
     // Foo(chars);
 ​
     string str;
     // scanf("%s", str);  https://blog.csdn.net/liu16659/article/details/86772657  不建议使用scanf输入string类型
     cin>>str;
     Foo2(str);
     system("pause");
     return 0;
 }

B.快速幂

 // B.快速幂
 #include<bits/stdc++.h>
 using namespace std;
 const long long Mod = 1e8 + 7;
 typedef long long ll;
 ll Pow(ll base, ll power)
 {
     ll result = 1;
     for(int i=1; i<=power; ++i)
     {
         result *= power;
         result %= 1000;  //每步结果提前进行取模
     }
     return result%1000;
 }
 // 快速幂
 // 所以我们快速幂算法的核心思想就是每一步都把指数分成两半,
 // 而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,
 // 所需要执行的循环次数也变小,而最后表示的结果却一直不会变
 ll fastPow(ll base, ll power)
 {
     ll result = 1;
     while(power>0)
     {
         if(power%2 == 0)
         {
             base = base*base % Mod;
             power /= 2;
         }
         else 
         {
             power -= 1;
             result = result*base % Mod;
             base = base*base % Mod;
             power /= 2;
         }
     }
     return result;
 }
 ll myPow(int x)
 {
     ll result = 0;
     for(int i=1; i<=x; ++i)
         result += fastPow(i, i);
     return (result+1)%Mod;
 }
 int main()
 {
     int x;
     while(cin>>x)
     {
         cout<<myPow(x)<<endl;
     }
     system("pause");
     return 0;
 }

C.求第k小的数

 // C.求第k小的数
 #include<bits/stdc++.h>
 using namespace std;
 int Partition(int a[], int low, int high);
 template<class Type>
 int RandomizedPartition(Type a[], int p, int r);
 template<class Type>
 void RandomizedQuickSort(Type a[], int p, int r);
 template<class Type>
 Type RandomizedSelect(Type a[], int p, int r, int k);
 int main()
 {
     // int n, k;
     // cin>>n>>k;
     // vector<int> vec;
     // for(int i=0; i<n; ++i)
     // {
     //     int num;
     //     scanf("%d", &num);
     //     vec.push_back(num);
     // }
     // sort(vec.begin(), vec.end());
     // cout<<vec[k-1];
 ​
     int a[100], n;
     while(~scanf("%d", &n))
     {
         memset(a, 0, sizeof(a));
         for(int i=0; i<n; i++) scanf("%d",&a[i]);
         int k;
         scanf("%d", &k);
         cout<<RandomizedSelect(a, 0, n-1, k)<<endl;
     }
     system("pause");
     return 0;
 }
 ​
 // 2.RandomizedSelect,平均时间复杂度O(n)
 int Partition(int a[], int low, int high)
 {
     int key = a[low];
     while(low<high)
     {
         while(low<high&&a[high]>key) --high;
         a[low] = a[high];
         while(low<high&&a[low]<=key) ++low;
         a[high] = a[low];
     }
     a[low] = key;
     return low;
 }
 template<class Type>
 int RandomizedPartition(Type a[], int p, int r)
 {
     int i = rand()%(r-p+1) + p;
     swap(a[i], a[p]);
     return Partition(a, p, r);
 }
 // template<class Type>
 // void RandomizedQuicksort(Type a[], int p, int r)  //随机快排
 // {
 //     if(p<r)
 //     {
 //         int q = RandomizedPartition(a, p, r);
 //         RandomizedQuicksort(a, p, q-1); //对左半段排序
 //         RandomizedQuicksort(a, q+1, r); //对右半段排序
 //     }
 // }
 template<class Type>
 Type RandomizedSelect(Type a[], int p, int r, int k)  //随机划分,选择
 {
     if(p == r) return a[p];
     int loc = RandomizedPartition(a, p ,r);
     int count = loc-p+1; //count为a[p:r]中的元素个数
     if(k<=count) return RandomizedSelect(a, p, loc, k);
     else return RandomizedSelect(a, loc+1, r, k-count);
 }

D.内部收益率

 // D.内部收益率
 #include<bits/stdc++.h>
 using namespace std;
 int main()
 {
     int a[100], n;
     while(scanf("%d", &n) && n)
     {
         for(int i=0; i<=n; i++) scanf("%d", a+i);
         double x = -1.0, y=1e6, irr, npv;
         for(int j=0; j<200; j++)
         {
             irr = (x+y)/2;   //枚举irr的取值范围[-1.0, 1e6], 二分法逼近 (至于这个范围怎么来的,我就不清楚了.数学问题)
             npv = 0;
             for(int k=0; k<=n; k++)
                 npv += 1.0*a[k]/pow(1+irr, k);
             if(fabs(npv)<1e-6) break;  //小于一个阈值,认为就是方程的解
             if(npv < 0) y = irr;
             if(npv > 0) x = irr;
         }
         printf("%.2lf\n", irr);
         memset(a, 0, sizeof(a));  //每次重置a数组
     }
     // cout<<9/2.25<<endl;
     system("pause");
     return 0;
 }

E.跳台阶

 // 跳台阶
 #include<bits/stdc++.h>
 using namespace std;
 // f(x) = f(x-1) + f(x-2)
 int climbStairsMemo(int n, vector<int>& memo)
 {
     if(memo[n]>0) return memo[n];  //记录数组
     if(n==1 || n==2) memo[n] = n;
     else memo[n] = climbStairsMemo(n-1, memo) + climbStairsMemo(n-2, memo);
     return memo[n];
 }
 int climbStairs(int n) {
     vector<int> memo(n+1, 0);
     return climbStairsMemo(n, memo);
 }
 ​
 // 滚动数组 将空间复杂度由O(n)优化成O(1)
 int climbStairs2(int n)
 {
     int p=0, q=0, r=1;
     for(int i=1; i<=n; i++)
     {
         p = q;
         q = r;
         r = p+q;
     }
     return r;
 }
 ​
 int main()
 {
     int n;
     cin>>n;
     cout<<climbStairs2(n)%1000000007<<endl;
     system("pause");
     return 0;
 }

2.Contest2445 - 毕老师算法实验二

传送门在这里 题目总览:

A.沙子的质量

 // A.沙子的质量  OJ作业一D题
 // 动态规划
 #include<bits/stdc++.h>
 using namespace std;
 const int inf = 0x3f3f3f3f;  //为什么用0x3f3f3f3f而不用0xffffff  https://blog.csdn.net/jiange_zh/article/details/50198097
 int Compute(int *nums, int n)
 {
     int Sum[n+1]={0};
     int DP[n+1][n+1];   //之前用DP[1005][1005],导致栈空间溢出  https://blog.csdn.net/kangyupl/article/details/90723367
     memset(DP, inf, sizeof(DP));
     for(int i=1; i<=n; i++)
     {
         Sum[i] = Sum[i-1] + nums[i];
         DP[i][i] = 0;
     }
     for(int Len=2; Len<=n; Len++)
         for(int left=1; left<=n-Len+1; left++)
         {
             int right = left+Len-1;
             for(int k=left; k<right; k++)
             {
                 DP[left][right] = min(DP[left][k]+DP[k+1][right]+Sum[right]-Sum[left-1], DP[left][right]);
             }
         }
     return DP[1][n];
 }
 int main()
 {
     int n;
     cin>>n;
     int nums[n+1];
     nums[0] = 0;
     for(int i=1; i<=n; ++i) cin>>nums[i]; 
     cout<<Compute(nums, n)<<endl;
     system("pause");
     return 0;
 }

B.最长公共子序列

 // B.最长公共子序列 OJ作业一F题
 // 动态规划
 #include<bits/stdc++.h>
 using namespace std;
 int longestCommonSequence(string a, string b)
 {
     int M = a.size();
     int N = b.size();
     vector<vector<int>> DP(M+1, vector<int>(N+1, 0));
     for(int i=1; i<=M; ++i)
     {
         for(int j=1; j<=N; ++j)
         {
             if(a[i-1]==b[j-1]) DP[i][j] = DP[i-1][j-1] + 1;
             else DP[i][j] = max(DP[i-1][j], DP[i][j-1]);
         }
     }
     return DP[M][N];
 }
 int main()
 {
     string a, b;
     cin>>a>>b;
     cout<<longestCommonSequence(a, b)<<endl;
     system("pause");
     return 0;
 }

C.三角形的路径权

 // C.三角形最小路径权
 // Leetcode 125题
 // 动态规划
 ​
 #include<bits/stdc++.h>
 using namespace std;
 // 理解错误,直角三角形的情况.
 int minimumTotal2(vector<vector<int>> &triangle)
 {
     int n = triangle.size();
     vector<vector<int>> dp(n, vector<int>(n));
     dp[0][0] = triangle[0][0];
     dp[1][0] = triangle[1][0], dp[1][1] = triangle[0][0]+triangle[1][1];
     if(n==2) return dp[1][1];
     for(int i=2; i<n; i++)
     {
         dp[i][0] = dp[i-1][1] + triangle[i][0];
         for(int j=1; j<=i-2; j++)
         {
             dp[i][j] = max(dp[i-1][j-1], dp[i-1][j+1]) + triangle[i][j];
         }
         dp[i][i] = dp[i-1][i-1] + triangle[i][i];
         dp[i][i-1] = dp[i-1][i-2] + triangle[i][i-1];
     }
     cout<<endl<<endl<<"DP数组更新为:"<<endl;
     for(const auto x:dp)
     {
         for(const int y:x) cout<<y<<" ";
         cout<<endl;
     }
     return *max_element(dp[n-1].begin(), dp[n-1].end());
 }
 ​
 // 看成等腰三角形
 int maximumTotal(vector<vector<int>> &triangle)
 {
     int n = triangle.size();
     vector<vector<int>> dp(n, vector<int>(n,0));
     dp[0][0] = triangle[0][0];
     for(int i=1; i<n; i++)
     {
         dp[i][0] = dp[i-1][0] + triangle[i][0];
         for(int j=1; j<n-1; j++) 
         {
             dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + triangle[i][j];
         }
         dp[i][i] = dp[i-1][i-1] + triangle[i][i];
     }
     return *max_element(dp[n-1].begin(), dp[n-1].end());
 }
 int main()
 {
     int n;
     cin>>n;
     vector<vector<int>> triangle(n, vector<int>(n));
     for(int i=0; i<n; i++)
     {
         for(int j=0; j<=i; j++)
             cin>>triangle[i][j];
     }
     cout<<maximumTotal(triangle)<<endl;
     system("pause");
     return 0;
 }

D.跳跃游戏Ⅱ

 // D.跳跃游戏Ⅱ 
 // LeetCode第45题
 // 贪心算法
 #include<bits/stdc++.h>
 using namespace std;
 // 思想就一句话:每次在上次能跳到的范围(end)内选择一个能跳的最远的位置(也就是能跳到max_far位置的点)作为下次的起跳点 !
 int Jump(vector<int> &nums)
 {
     int n = nums.size();
     int max_far = 0;  //目前能够跳到的最远位置
     int step = 0;
     int end = 0;  //上次跳跃可到达的范围右边界
     for(int i=0; i<n-1; i++)   //<n-1,最后一个元素不用遍历.
     {
         max_far = max(i+nums[i], max_far);
         if(i == end)
         {
             end = max_far;
             step++;
         }
     }
     return step;
 }
 int main()
 {
     int n;
     cin>>n; 
     vector<int> nums(n);
     for(int i=0; i<n; i++) cin>>nums[i];
     cout<<Jump(nums)<<endl;
     system("pause");
     return 0;
 }

E.字母排序

 // E.字母排序
 // 最长不降子序列
 #include<bits/stdc++.h>
 using namespace std;
 // 1.LIS ---> LCS  最长递增子序列(排序+LCS)
 // const int N = 1010;
 // int DP[N][N];
 // int DIR[N][N];
 // int LCS_Length(string a, string b)
 // {
 //     int m = a.size();
 //     int n = b.size();
 //     for(int i=1; i<=m; i++)
 //     {
 //         for(int j=1; j<=n; j++)
 //         {
 //             if(a[i-1] == b[j-1])
 //             {
 //                 DP[i][j] = DP[i-1][j-1] + 1;
 //                 DIR[i][j] = 1;
 //             }
 //             else if(DP[i-1][j] > DP[i][j-1])
 //             {
 //                 DP[i][j] = DP[i-1][j];
 //                 DIR[i][j] = 2;
 //             }
 //             else 
 //             {
 //                 DP[i][j] = DP[i][j-1];
 //                 DIR[i][j] = 3;
 //             }
 //         }
 //     }
 //     return DP[m][n];
 // }
 // void LCS(string a, int i, int j)
 // {
 //     if(i==0 || j==0) return;
 //     if(DIR[i][j] == 1)
 //     {
 //         LCS(a, i-1, j-1);
 //         cout<<a[i-1];
 //     }
 //     else if(DIR[i][j] == 2) LCS(a, i-1, j);
 //     else if(DIR[i][j] == 3) LCS(a, i, j-1);
 // }
 // string RD(string b, int &add)  //去重函数  hhh变为h
 // {
 //     bool Flag[b.size()] = {false};
 //     for(int i=1; i<b.size(); i++)
 //     {
 //         if(b[i] == b[i-1]) 
 //         {
 //             add++;
 //             Flag[i] = true;
 //         }
 //     }
 //     for(int i=0; i<b.size(); i++)
 //     {
 //         if(Flag[i] == 1) b[i] = '.';
 //     }
 //     // cout<<b<<endl;
 //     b.erase(std::remove(b.begin(), b.end(), '.'), b.end());  //去重操作
 //     return b;
 // }
 // int LIS_Length(string a, string b)
 // {
 //     return LCS_Length(a, b);
 // }
 // int main()
 // {
 //     string a, str;
 //     cin>>a;
 //     cin.ignore();   //空格
 //     getline(cin, str);
 //     str += ' ';
 //     string b;
 //     int Start_pos = 0;
 //     int add = 0;
 //     for(int i=0; i<str.size(); i++)
 //     {
 //         if(str[i] == ' ')
 //         {
 //             // cout<<"Flag"<<i<<endl;
 //             b = str.substr(Start_pos, i-Start_pos);
 //             // cout<<b<<endl;
 //             RD(b, add);
 //             cout<<LIS_Length(a, b)+add;
 //             Start_pos = i+1;
 //             add = 0;
 //         }
 //     }
 //     // string test;
 //     // cin>>test;
 //     // int add = 0;
 //     // cout<<RD(test, add)<<" "<<add<<endl;
 //     // cout<<test<<endl;
 //     system("pause");
 //     return 0;
 // }
 ​
 // 2.DP
 // O(n^2)
 // int LengthOfLIS(vector<int> &nums)
 // {
 //     int n = nums.size();
 //     if(n==0) return 0;
 //     vector<int> dp(n, 1);
 //     for(int i=0; i<n; i++)
 //     {
 //         for(int j=0; j<i; j++)
 //         {
 //             if(nums[i] > nums[j])
 //             {
 //                 dp[i] = max(dp[j]+1, dp[i]);
 //             }
 //         }
 //     }
 //     return *max_element(dp.begin(), dp.end());
 // }
 // int main()
 // {
 //     int n;
 //     while(scanf("%d", &n) && n)
 //     {
 //         vector<int> nums(n);
 //         for(int i=0; i<n; i++) scanf("%d", &nums[i]);
 //         cout<<LengthOfLIS(nums)<<endl;
 //     }
 //     system("pause");
 //     return 0;
 // }
 ​
 // 3.贪心 + 二分查找
 // 维护一个一维数组B,并且这个数组是动态扩展的,初始大小为1,
 //B[i]表示最长上升子序列长度是i的所有子串中末尾最小的那个数,根据这个数字,我们可以比较知道,
 //只要当前考察的这个数比B[i]大,那么当前这个数一定能通过B[i]构成一个长度为i+1的上升子序列。
 //如果当前考察的数并没有数组尾部的B[i]大,那么我们选择在B数组中找到第一个大于当前考察数的元素,并且更换.
 // 正确!!!
 int BinarySearch(vector<int> &nums, int l, int r, int target)   //在nums数组中找到第一个大于target的数,然后更新它
 {
     if(l == r) return l;
     int mid;
     while(l <= r)
     {
         mid = (l+r)/2;
         if(nums[mid] == target) return mid;  //return mid!
         else if(nums[mid] > target) r = mid-1;
         else l = mid+1;
     }
     return l;
 }
 int LengthOfLIS(vector<int> &nums)
 {
     int n = nums.size();
     vector<int> B(n+1);
     B[0] = 0;
     B[1] = nums[0];
     int len = 1; //表示B数组的长度
     for(int i=1; i<n; i++)
     {
         if(nums[i] > B[len])
         {
             B[++len] = nums[i]; 
         }
         else if(nums[i] < B[len])
         {
             int pos = BinarySearch(B, 1, len, nums[i]);  //在B数组中找到第一个大于nums[i]的元素位置
             cout<<pos<<" "<<i<<" "<<nums[i]<<endl;
             B[pos] = nums[i];
         }
     }
     for(const int x:B) cout<<x<<" ";
     cout<<endl;
     return len;
 }
 ​
 // 力扣! https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/zui-chang-shang-sheng-zi-xu-lie-by-leetcode-soluti/
 // 考虑一个简单的贪心,如果我们要使上升子序列尽可能的长,则我们需要让序列上升得尽可能慢,因此我们希望每次在上升子序列最后加上的那个数尽可能的小。
 // 我们依次遍历数组 nums 中的每个元素,并更新数组 d 和 len 的值。如果nums[j] > d[len] 则更新 len = len + 1
 // 否则在 d[1...len] 中 找到 d[i-1] < nums[j] <  d[i]的pos值,然后更新d[i] = nums[j]
 int lengthOfLIS(vector<int> &nums)
 {
     int len = 1, n = int(nums.size());
     if(n == 0) return 0;
     vector<int> d(n+1, 0);
     d[len] = nums[0];
     for(int i=1; i<n; ++i)
     {
         if(nums[i] > d[len])
             d[++len] = nums[i];
         else
         {
             int l = 1, r = len, pos = 0;        //如果找不到说明所有的数都比nums[i]大,此时要更新d[1]
             while(l <= r)
             {
                 int mid = (l+r) >> 1;
                 if(d[mid] < nums[i])
                 {
                     pos = mid;
                     l = mid+1;
                 }
                 else r = mid-1;
             }
             d[pos+1] = nums[i];
         }
     }
     return len;
 }
 int main()
 {
     int t;
     cin>>t;
     while(t--)
     {
         int n;
         cin>>n;
         vector<int> nums(n);
         for(int i=0; i<n; i++)
             cin>>nums[i];
         cout<<LengthOfLIS(nums)<<endl;
     }
     system("pause");
     return 0;
 }

3.Contest2453 - 毕老师算法实验三

传送门在这里 题目总览:

A.Homework

 // D.Homework
 // 正确!
 #include<bits/stdc++.h>
 using namespace std;
 bool cmp(pair<double, double> a, pair<double, double> b)
 {
     return a.second/a.first > b.second/b.first;
 }
 int main()
 {
     int M, N;
     while(scanf("%d%d", &M, &N) && (M && N))
     {
         vector<pair<double, double>> vec;
         double time, value;
         for(int i=0; i<M; ++i)
         {
             scanf("%lf%lf", &time, &value);
             vec.push_back(pair<double, double>(time, value));
         }   
         sort(vec.begin(), vec.end(), cmp);
         double TimeTotal = N;
         double ValueTotal = 0;   //double类型,如果写为int类型答案错误
         for(const auto x:vec) cout<<"("<<x.first<<","<<x.second<<")"<<endl;
         for(const pair<double, double> x:vec)
         {
             if(TimeTotal-x.first >= 0)
             {
                 cout<<"Flag1"<<endl;
                 ValueTotal += x.second;
                 TimeTotal -= x.first;
             }
             else 
             {
                 ValueTotal += TimeTotal * x.second/x.first;
                 break;
             }
         }
         printf("%.2lf\n", ValueTotal);
     }
     system("pause");
     return 0;
 }

B.区间包含问题

 // E.区间包含问题
 // 贪心算法  类似于活动安排问题
 #include<bits/stdc++.h>
 using namespace std;
 const int maxn = 10010;
 struct Node
 {
     int left, right;
 }node[maxn];
 bool cmp(Node a, Node b)
 {
     return a.right < b.right;
 }
 int main()
 {
     int n, m;
     scanf("%d %d", &n, &m);
 ​
     for(int i=0; i<n; ++i) 
     {
         scanf("%d %d", &node[i].left, &node[i].right);
         // node[i].right++;
     }
     sort(node, node+n, cmp);
     int l, r;
     for(int i=0; i<m; ++i) 
     {
         scanf("%d %d", &l, &r);
         int pos = l, ans = 0;
         for(int j=0; j<n; ++j)
         {
             if(node[j].left>=pos && node[j].right<=r)
             {
                 cout<<l<<" "<<r<<endl;
                 cout<<j<<" "<<node[j].left<<" "<<node[j].right<<endl;
                 ans++;
                 pos = node[j].right;
             }
         }
         printf("%d\n", ans);
     }
     system("pause");
     return 0;
 }

C.最长子序列

 // F.最长子序列(最大子段和)
 #include<bits/stdc++.h>
 using namespace std;
 // 1.递归分治法
 // f(i) = max(f(i-1)+nums[i], nums[i])  考虑f(i-1)带来的是正能量还是负能量
 // f(i) 代表以第 i 个数结尾的「连续子数组的最大和」,那么很显然我们要求的答案就是:
 // max(0-i-1){f[i]}
 int maxSubArray(vector<int> &nums)
 {
     int n = nums.size();
     if(n==0) return {};
     if(n==1) return nums[0];
     vector<int> f(n);
     f[0] = nums[0];
     for(int i=1; i<n; ++i)
     {
         f[i] = max(f[i-1]+nums[i], nums[i]);
     } 
     for(const int x:f) cout<<x<<" ";
     cout<<endl;
     return *max_element(f.begin(), f.end());  //记住不是返回f[n-1]
 }
 int maxSubArray2(vector<int> &nums)
 {
     int n = nums.size();
     if(n==0) return {};
     int pre = 0, maxAns = nums[0];
     for(const int  x:nums)
     {
         pre = max(pre+x, x);  //pre记录当前x前面的连续子数组的最大和,即f[i-1],不断更新. 类似于滚动数组 
         maxAns = max(maxAns, pre);
     }
     return maxAns;
 }
 int main()
 {
     int n;
     while(~scanf("%d", &n))
     {
         vector<int> nums(n);
         for(int i=0; i<n; ++i) scanf("%d", &nums[i]);
         cout<<maxSubArray(nums)<<endl;
     }
     system("pause");
     return 0;
 }

D.三值排序

 // D.三值排序
 #include<bits/stdc++.h>
 using namespace std;
 int ThreeSort(vector<int> &nums)
 {
     int n = nums.size();
     int a=0, b=0, c=0;
     for(int i=0; i<n; ++i)
     {
         if(nums[i]==1) a++;
         else if(nums[i]==2) b++;
         else if(nums[i]==3) c++; 
     }
     int dif[4][4] = {0};
     for(int i=0; i<a; i++) 
         if(nums[i] != 1) dif[1][nums[i]]++;
     for(int i=a; i<a+b; i++)
         if(nums[i] != 2) dif[2][nums[i]]++;
     for(int i=a+b; i<n; i++)
         if(nums[i] != 3) dif[3][nums[i]]++;
     int ans = 0, sum = 0;
     for(int i=1; i<4; i++)
     {
         for(int j=i+1; j<4; j++)
         {
             if(dif[i][j] <= dif[j][i])
             {
                 ans += dif[i][j];
                 sum += dif[j][i] - dif[i][j]; 
             }
             else
             {
                 ans += dif[j][i];
                 sum += dif[i][j] - dif[j][i];
             }
         }
     }
     ans = ans + sum/3*2;  //三个数字都不在自己该在的位置,但是只需要两步就能变得有序:213变为123只需两步  312 132等等同样
     return ans;
 }
 int main()
 {
     int n;
     cin>>n;
     vector<int> nums(n);
     int a=0, b=0, c=0;
     for(int i=0; i<n; ++i) 
         scanf("%d", &nums[i]);
     cout<<ThreeSort(nums)<<endl;
     system("pause");
     return 0;
 }

E.法师康的工人

 // E.法师康的工人
 // 这一题有点问题,我好像没改过来
 #include<bits/stdc++.h>
 using namespace std;
 bool cmp(pair<int, int> a, pair<int, int> b)
 {
     return a.second < b.second;
 }
 int main()
 {
     int n;
     cin>>n;
     vector<pair<int, int>> vec;
     int left, right;
     for(int i=0; i<n; ++i)
     {
         scanf("%d%d", &left, &right);
         vec.push_back(pair<int, int>(left, right));
     }
     sort(vec.begin(), vec.end(), cmp);
     int left_border = vec[0].first;
     int right_border = vec[0].second;
     int max_ContinuousLength = right_border-left_border;
     int max_IntervalLength = 0;
     for(int i=1; i<n; ++i)
     {
         if(vec[i].first <= right_border)
         {
             right_border = max(right_border, vec[i].second);
             left_border = min(left_border, vec[i].first);
         }    
         else
         {
             max_ContinuousLength = max(max_ContinuousLength, right_border-left_border);
             max_IntervalLength = max(max_IntervalLength, vec[i].first-right_border);
             left_border = vec[i].first;  //出现间隔,重置边界
             right_border = vec[i].second;
         }
     }
     max_ContinuousLength = max(max_ContinuousLength, right_border-left_border);
 ​
     // 防止 2 (100 500)  (400 900)这种没有间断的情况出现,直接跳出循环的话  
     cout<<max_ContinuousLength<<" "<<max_IntervalLength<<endl;
     system("pause");
     return 0;
 }
 ​
 // 10
 // 2 3
 // 4 5
 // 6 7
 // 8 9
 // 10 11
 // 12 13
 // 14 15
 // 16 17
 // 18 19
 // 1 20
 // 19 1
 // 请按任意键继续. . .
 // 正确答案:19 0    错误的原因?咋改

4.Contest2462 - 毕老师算法实验四

传送门在这里 题目总览:

A.凯撒加密法

 // A.ż•ČöĂÜÂë
 #include<bits/stdc++.h>
 using namespace std;
 string CaesarCipher(string ciphertext, int n)
 {
     int length = ciphertext.size();
     for(int i=0; i<length; ++i)
     {
         if(isupper(ciphertext[i]))
             ciphertext[i] = 'A' + (ciphertext[i]-'A'-n+26)%26;
         else if(islower(ciphertext[i]))
             ciphertext[i] = 'a' + (ciphertext[i]-'a'-n+26)%26;
     }
     return ciphertext;
 }
 int main()
 {
     int T;
     scanf("%d", &T);
     // for(int i=0; i<T; ++i)
     // {
     //     string ciphertext;
     //     // cin>>ciphertext;
     //     cin.ignore();
     //     getline(cin, ciphertext);
     //     int k;
     //     cin>>k;
     //     k = k%26;
     //     cout<<CaesarCipher(ciphertext, k)<<endl;
     // }
     string str[T];
     int change[T];
     for(int i=0; i<T; ++i)
     {
         cin>>str[i];
         cin>>change[i];
         change[i] %= 26;
     }
     for(int i=0; i<T; i++)
     {
         cout<<CaesarCipher(str[i], change[i])<<endl;
     }
 ​
     system("pause");
     return 0;
 }

B.维吉尼亚密码

 // B.¸ĽźŞÄáŃÇĂÜÂë
 #include<bits/stdc++.h>
 using namespace std;
 string fill(string key, string plainText)
 {
     int len1 = key.size();
     int len2 = plainText.size();
     if(len1 < len2) 
     {
         int num = len2 - len1;
         string temp = key;
         for(int i=0; i<num; ++i)
         {
             key += temp[i%len1];
         }
     }
     for(int i=0; i<len2; ++i)
     {
         if(islower(key[i]))
             key[i] -= 32;
     }
     return key;
 }
 int main()
 {
     string key, cipherText;
     cin>>key>>cipherText;
     key = fill(key, cipherText);
     // cout<<key<<endl;
     int len = cipherText.size();
     string plainText;
     int change;
     for(int i=0; i<len; ++i)
     {
         change = key[i] - 'A';
         // cout<<i<<": "<<change<<endl;
         if(isupper(cipherText[i]))
             plainText.push_back('A' + (cipherText[i]-'A'- change + 26)%26);
         else
             plainText.push_back('a' + (cipherText[i]-'a'- change + 26)%26);
     }
     cout<<plainText<<endl;
     system("pause");
     return 0;
 }

C.简单的密码

 #include<bits/stdc++.h>
 using namespace std;
 int main()
 {
     int n;
     int f[35] = {0, 0, 0, 1};
     for(int i=4; i<=30; ++i)
         f[i] = f[i-1]*2 + pow(2, i-4) - f[i-4];
     while(cin>>n && n>=1 && n<=30)
         cout<<f[n]<<endl;
     system("pause");
     return 0;
 }

D.有趣的素数

 // 带佬代码
 #include<iostream>
 #include<stdio.h>
 #include<string.h>
 using namespace std;
 int n,ans,last;
 bool visited[32];
 bool isPrime[40]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0};
 void pc(int cur)
 {
     if(cur == n && isPrime[1+last])
     {
         ans++;
         return;
     }
     for(int i = 2; i <= n; i++)
     {
         if(!visited[i] && isPrime[last+i])
         {
             int t = last;
             last = i;
             visited[i] = true;
             pc(cur+1);
             visited[i] = false;
             last = t;
         }
     }
 }
 int main()
 {
     while(~scanf("%d",&n))
     {
         memset(visited,0,sizeof(visited));
         ans = 0;
         last = 1;
         pc(1);
         printf("%d\n",ans);
     }
     return 0;
 }

E.数据加密

 // E.数据加密
 #include<bits/stdc++.h>
 using namespace std;
 string CipherCompute(string PlainText)
 {
     int n = PlainText.size();
     string ans;
     if(n==0) return {};
     if(n==1) return PlainText;
     int left = 0, right = n-1;
     while(n>0)
     {
         if(PlainText[left] < PlainText[right])
         {
             ans += PlainText[left];
             left++;
             n--;
         }
         else if(PlainText[left] > PlainText[right])
         {
             ans += PlainText[right];
             right--;
             n--;
         }
         else 
         {
             int temp_left = left+1, temp_right = right-1;
             while(temp_left<n && temp_right>=0 && temp_left <= temp_right && PlainText[temp_left] == PlainText[temp_right])
             {
                 temp_left++;
                 temp_right--;
             } 
             if(PlainText[temp_left]>PlainText[temp_right])
             {
                 ans += PlainText[right];
                 right--;
                 n--;
             }
             else
             {
                 ans += PlainText[left];
                 left++;
                 n--;
             } 
         }
     }
     return ans;
 }
 int main()
 {
     int t;
     cin>>t;
     while(t--)
     {
         int n;
         cin>>n;
         string PlainText;
         cin>>PlainText;
         string Cipher = CipherCompute(PlainText);
         cout<<Cipher<<endl;
     }
     system("pause");
     return 0;
 }
 ​
 // 带佬代码
 #include<iostream>
 #include<stdio.h>
 #include<string.h>
 using namespace std;
 int main()
 {
     int n;
     char str[2005],ans[2005];
     while(~scanf("%d",&n))
     {
         scanf("%s",str);
         int i = 0,j = n-1;
         while(i <= j)
         {
             bool flag = false;
             for(int k = 0; i+k < j-k; k++)
             { 
                 if(str[i+k] < str[j-k])
                 {
                     flag = true;
                     break;
                 }
                 if(str[i+k] > str[j-k]) break;
             }
             if(flag) printf("%c",str[i++]);
             else printf("%c",str[j--]);
         }
         printf("\n");
     }
     return 0;
 }

CV工程师👨 (~ ̄▽ ̄)~ 如果大家觉得本篇文章对自己有所帮助的话,不妨去我的个人博客---乔治的编程小屋逛逛吧.