当前位置: 首页 > wzjs >正文

量子秘密网站怎么做赣州seo排名

量子秘密网站怎么做,赣州seo排名,金山手机网站建设,app需要建网站吗目录 Day1 kotori和抽卡(二) ruby和薯条 循环汉诺塔 Day2 最小差值 kotori和素因子 dd爱科学1.0 Day3 kanan和高音 拜访 买卖股票的最好时机(四) Day4 AOE还是单体? kotori和n皇后 取金币 Day5 矩阵转置 四个选项 接雨…

目录

Day1

kotori和抽卡(二)

ruby和薯条

循环汉诺塔

Day2 

最小差值

kotori和素因子

dd爱科学1.0

Day3 

kanan和高音

拜访

买卖股票的最好时机(四)

Day4

AOE还是单体?

kotori和n皇后

取金币

Day5 

矩阵转置

四个选项

接雨水问题

Day6

疯狂的自我检索者

栈和排序

加减


Day1

kotori和抽卡(二)

解法:数学

#include <iostream>
#include <cmath>
using namespace std;double n, m, a = 1, b = 1, c = 1, d = 1;int main()
{cin >> n >> m;for (int i = n; i >= n - m + 1; i--)a *= i;for (int i = m; i >= 1; i--)b *= i;// for(int i=0;i<m;i++) c*=0.8;// for(int i=0;i<n-m;i++) d*=0.2;printf("%0.4f", a / b * pow(0.8, m) * pow(0.2, n - m));// printf("%0.4f",n*0.8/m);return 0;
}

ruby和薯条

解法1:暴力

两层for循环一个一个比较枚举统计出队数(超时)

解法2:排序 + 二分

先排升序,再以数组的每个数(假设为a[i])为基准值统计出[a[i] + l ,a[i] +r]区间的个数,此时采取两次二分分别求出左端点与右端点;

解法3:排序 + 滑动窗口

与小红的子串的思路一样:先排序,再用滑动窗口统计出 [0,r]和 [0,l-1]区间的队数后相减就是 [l,r]中的队数(注意统计合法的队数时是:right - left 而不是 right -left + 1)

//二分
#include <iostream>
#include <algorithm>
using namespace std;typedef long long LL;
const int N = 2e5 + 10;
LL n, l, r, a[N], ret;int main()
{cin >> n >> l >> r;for (int i = 0; i < n; i++)cin >> a[i];sort(a, a + n);for (int i = 0; i < n; i++){if (a[i] + l > a[n - 1])break;//[a[i]+l,a[i]+r] 二分区间:找左右端点int left = 0, right = n - 1, begin = 0, end = 0;while (left < right){int mid = (left + right) / 2;if (a[mid] < a[i] + l)left = mid + 1;elseright = mid;}begin = left;left = 0, right = n - 1;while (left < right){int mid = (left + right + 1) / 2;if (a[mid] > a[i] + r)right = mid - 1;elseleft = mid;}end = left;ret += end - begin + 1;}cout << ret << endl;return 0;
}//滑动窗口
#include <iostream>
#include <algorithm>
using namespace std;typedef long long LL;
const int N = 2e5 + 10;
LL n, l, r, a[N];LL fun(int tmp)
{LL ret = 0;for (int left = 0, right = 0; right < n; right++){while (a[right] - a[left] > tmp)left++;ret += right - left;}return ret;
}int main()
{cin >> n >> l >> r;for (int i = 0; i < n; i++)cin >> a[i];sort(a, a + n);// 区间 [0,r] 和 [0,l-1]cout << fun(r) - fun(l - 1) << endl;return 0;
}

循环汉诺塔

解法:找规律

当n=1时,A->B的操作是1,A->C的操作是2;

当n=2时,A->B的操作是1+1+1=3,A->C的操作是2+1+1+1+2=7;

当n=3时:

A->B的操作是:先把n-1个小金片从A->C上,这个操作在n=2时已经计算过了,操作数为:7,再把A的大金片移到B上,操作数为1,再把C上全部金片移到B上,这个操作我们计算过了吗?当然!C->B上与A->C上本质都是要移动两格,所以操作数为7,计算结果为:7 + 1 + 7 =15;把n=2时 A->C的操作次数设为y,公式为:2y + 1

A->C的操作也同理,结果为:7+1+5+1+7=21,把n=2时 A->B的操作次数设为x,公式为:2y + x + 1;

#include <iostream>
using namespace std;typedef long long LL;
const int N = 1e9 + 7;
LL n, x = 1, y = 2, a, b;int main()
{cin >> n;n -= 1;while (n--){a = (2 * y + 1) % N;b = (2 * y + x + 2) % N;x = a;y = b;}cout << x << ' ' << y << endl;return 0;
}

Day2 

最小差值

解法:排序

排序后依次找最小值 

class Solution
{
public:int minDifference(vector<int> &a){sort(a.begin(), a.end());long long ret = 0x3f3f3f3f3f3f3f3f;for (int i = 0; i < a.size() - 1; i++){ret = min(ret, (long long)abs(a[i] - a[i + 1]));}return ret;}
};

kotori和素因子

解法:dfs

先把每个数的素因子统计到数组中;

在对每一个数的素因子的情况进行递归枚举,找到最小值

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;int n, a[10], path, ret = 0x3f3f3f3f;
bool vis[1001];void dfs(int pos, vector<vector<int>> &sv)
{if (pos == n){ret = min(ret, path);return;}for (auto &e : sv[pos]){if (!vis[e]){path += e;vis[e] = true;dfs(pos + 1, sv);vis[e] = false;path -= e;}}
}bool fun(int a)
{for (int i = 2; i <= sqrt(a); i++){if (a % i == 0)return false;}return true;
}int main()
{cin >> n;vector<vector<int>> sv(n);for (int i = 0; i < n; i++){cin >> a[i];for (int j = 2; j <= a[i]; j++) // 如果本身是素数就选它,所以加上<+{if (a[i] % j == 0 && fun(j))sv[i].push_back(j);}}dfs(0, sv);if (ret == 0x3f3f3f3f)cout << -1 << endl;elsecout << ret << endl;return 0;
}

dd爱科学1.0

解法:贪心 + 二分

题目转化为求最长递增子序列后将总大小减去它即可

#include <iostream>
#include <string>
#include <vector>
using namespace std;int n;
string s;
vector<char> v;int main()
{cin >> n >> s;for (int i = 0; i < n; i++){if (v.empty() || v.back() <= s[i])v.push_back(s[i]);else{int left = 0, right = v.size() - 1;while (left < right){int mid = (left + right) / 2;if (s[i] >= v[mid])left = mid + 1;elseright = mid;}v[left] = s[i];}}cout << n - v.size() << endl;return 0;
}

Day3 

kanan和高音

解法:双指针

从前往后遍历,⽤双指针找出⼀段能唱完的区域,然后更新指针继续找下⼀段

#include <iostream>
using namespace std;int n, a[200010], ret;int main()
{cin >> n;for (int i = 0; i < n; i++)cin >> a[i];for (int i = 0; i < n;){int j = i;while (j + 1 < n && a[j + 1] - a[j] <= 8)j++;ret = max(ret, j - i + 1);i = j + 1; // 快}cout << ret << endl;return 0;
}

拜访

解法:bfs

1.开辟俩个二维数组dist,cnt用来储存距离信息与方案信息,dist数组全部初始化为-1,cnt数组全部初始化为0;

2.从开始位置【i,j】出发,即 dist [i][j] = 0表示不用移动距离,cnt [i][j] = 1表示到达开始位置有一种方案数(什么都不用做),把【i,j】加入到队列中开始层序遍历;

3.每次遍历把队列中坐标全部取出来进行上下左右四个方向遍历,第一次到达该位置就统计dist和cnt位置的值;不是第一次就看看此时dist位置的值是否等于上一次dist位置的值加1,是的话就说明又找到了到达该位置的方案,此时cnt位置的值累加上一次cnt位置的值(有点抽象具体看代码好理解)

#include <cstring>
class Solution {
public:// vector<int> ret;// int cnt=0,tmp=0x3f,path=0,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};// bool vis[10][10]={false};// void dfs(vector<vector<int>>& C,int a,int b,int n,int m)//超时// {//     if(C[a][b]==2)//     {//         ret.push_back(path);//         tmp=min(tmp,path);//         return;//     }//     for(int k=0;k<4;k++)//     {//         int x=dx[k]+a,y=dy[k]+b;//         if(x>=0&&x<n&&y>=0&&y<m&&!vis[x][y]&&C[x][y]!=-1)//         {//             vis[x][y]=true;//             path++;//             dfs(C,x,y,n,m);//             path--;//             vis[x][y]=false;//         }//     }// }queue<pair<int,int>> q;int dist[10][10],cnt[10][10]={0};int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};void bfs(vector<vector<int>>& C,int n,int m){while(q.size()){int sz=q.size();while(sz--){auto [a,b]=q.front();q.pop();if(C[a][b]==2){continue;}for(int k=0;k<4;k++){int x=dx[k]+a,y=dy[k]+b;//if(dist[x][y]==dist[a][b]+1) cnt[x][y]+=cnt[a][b];//统计最短方案数//if(x>=0&&x<n&&y>=0&&y<m&&dist[x][y]==-1&&C[x][y]!=-1)if(x>=0&&x<n&&y>=0&&y<m&&C[x][y]!=-1){if(dist[x][y]==-1){dist[x][y]=dist[a][b]+1;cnt[x][y]+=cnt[a][b];q.push({x,y});}else if(dist[x][y]==dist[a][b]+1){cnt[x][y]+=cnt[a][b];}}}}}}int countPath(vector<vector<int> >& CityMap, int n, int m) {memset(dist,-1,sizeof(dist));for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(CityMap[i][j]==1){//vis[i][j]=true;//dfs(CityMap,i,j,n,m);//开始位置进行初始化dist[i][j]=0;cnt[i][j]=1;q.push({i,j});bfs(CityMap,n,m);break;}}}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(CityMap[i][j]==2) return cnt[i][j];}}return -1;// for(auto& e:ret)// {//     if(e==tmp) cnt++;// }// return cnt;}
};

买卖股票的最好时机(四)

解法:动态规划

股票问题的多状态问题

#include <cstring>
using namespace std;int n, k, a[1010], f[1010][110], g[1010][110];int main()
{cin >> n >> k;for (int i = 0; i < n; i++)cin >> a[i];memset(f, -0x3f3f3f3f, sizeof(f)); // 有股票状态memset(g, -0x3f3f3f3f, sizeof(g)); // 无股票状态f[0][0] = -a[0], g[0][0] = 0;      // 初始化for (int i = 1; i <= n; i++){for (int j = 0; j <= k; j++){f[i][j] = max(f[i - 1][j], g[i - 1][j] - a[i - 1]);g[i][j] = g[i - 1][j];if (j - 1 >= 0)g[i][j] = max(g[i][j], f[i - 1][j - 1] + a[i - 1]);}}int ret = -0x3f3f3f3f;for (int j = 0; j <= k; j++)ret = max(ret, g[n][j]);cout << ret << endl;return 0;
}

Day4

解法:贪心

当 x 大于等于 n时,使用AOE让怪物掉血快;

当 x 小于 n时,使用单体让怪物掉血快;

以上策略很好想,但如何写代码呢?

数据量很大,一次一次模拟必超时;

优化方案:

使用AOE本质是要消灭n-x个怪物后使用单体,所以:

先排序,使用AOE消灭次数为:a[ n - x -1]* x(数组从0开始要减1);

再让AOE攻击后剩下的n - x怪物使用单体,也就是累加操作

AOE还是单体?

#include <iostream>
#include <algorithm>
using namespace std;typedef long long LL;
const int N = 2e5 + 10;
LL n, x, a[N], ret;int main()
{cin >> n >> x;for (int i = 0; i < n; i++)cin >> a[i];if (x >= n){for (auto &e : a)ret += e;cout << ret << endl;return 0;}sort(a, a + n);ret += a[n - x - 1] * x;for (int i = n - x; i < n; i++)ret += a[i] - a[n - x - 1];cout << ret << endl;return 0;
}

kotori和n皇后

解法:哈希表

用四个哈希表储存坐标行,列,主对角线,副对角线的数据;

如果遇到坐标在四个哈希表内就说明此时的皇后会与前面的皇后相互攻击,用变量tmp将它标记起来即可,接下来的坐标就不用管了:

因为当询问的第i个皇后的i大于tmp时答案都是Yes!不管第i个皇后有没有与前面的i-1个皇后相互攻击

#include <iostream>
#include <unordered_set>
using namespace std;typedef long long LL;
LL k, x1, y1, t, i, tmp;
unordered_set<LL> row, col, dig1, dig2;int main()
{cin >> k;for (int j = 1; j <= k; j++){cin >> x1 >> y1;if (tmp)continue;if (row.find(x1) != row.end() || col.find(y1) != col.end() ||dig1.find(y1 - x1) != dig1.end() || dig2.find(y1 + x1) != dig2.end()){tmp = j;}else{row.insert(x1);col.insert(y1);dig1.insert(y1 - x1);dig2.insert(y1 + x1);}}cin >> t;while (t--){cin >> i;if (tmp == 0 || i < tmp)cout << "No" << endl; // 还有tmp为0找不到相互攻击的情况elsecout << "Yes" << endl;}
}

取金币

解法:动态规划

区间dp问题;

状态表示

dp[i][j]表示从[i,j]区间内的金币全部取走此时的最大积分  

状态转移方程

假设在【i,j】区间内定义一个k,我们先取k位置上的金币,所以【i,j】区间被分为三部分:【i,k-1】k 【k+1,j】将三部分使用状态表示,则:

dp[i][j] = dp[i][k-1] + dp[k+1][j] + a[i-1] * a[k] * a[j+1];

初始化

a.取a[i-1] 和 a[j+1]的值可能越界,所以要在原数组中开头和结尾添加1(使得不影响填表),填表就从【1,n】内填表(n为原数组的大小);同样dp表也要多两行两列且为了不影响填表,这里只初始化为0

填表顺序

从下往上,从左往右

返回值

dp[1][n]

class Solution
{
public:int getCoins(vector<int> &coins){int n = coins.size();// 初始化coins.insert(coins.begin(), 1);coins.push_back(1);vector<vector<int>> dp(n + 2, vector<int>(n + 2));for (int i = n; i >= 1; i--){for (int j = i; j <= n; j++){for (int k = i; k <= j; k++){dp[i][j] = max(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + coins[i - 1] * coins[k] * coins[j + 1]);}}}return dp[1][n];}
};

Day5 

矩阵转置

解法:模拟

按照题意进行模拟 

#include <iostream>
using namespace std;long long n, m, a[10][10];int main()
{cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++)cin >> a[i][j];}for (int j = 0; j < m; j++){for (int i = 0; i < n; i++)cout << a[i][j] << ' ';cout << endl;}return 0;
}

四个选项

解法:dfs

暴力枚举12个选项,分别填入四个选项看看是否满足要求,知道把12选项都填完就说明找到了一种方案...统计所有合法的方案数返回

怎么知道选择的选项合法?

定义全局数组a把na,nb,nc,nd的值填进来,当填到某个位置时去数组a看看是否还能选择(前面选择后--,为0就说明不能选了)

怎么知道题目给出的位置填的选项都相同?

定义二维数组vis进行标记,把信息统计进vis中:vis[x][y] = vis[y][x] = true

再用vector统计当前选项选的是什么,当递归到某个位置时就结合vis进行判断

#include <iostream>
#include <vector>
using namespace std;int a[5], m, x, y, ret;
bool vis[13][13];
vector<int> path;bool IsSame(int pos, int i)
{// for(int j=1;j<=12;j++)//path越界for (int j = 1; j < pos; j++) // 去pos前面看看是否需要选项与前面的选项相同{if (vis[pos][j] == true && i != path[j])return false;}return true;
}void dfs(int pos)
{if (pos > 12){ret++;return;}for (int i = 1; i <= 4; i++){if (a[i] == 0)continue; // 该选项选完了if (!IsSame(pos, i))continue; // 相同题目是否选的是相同的path.push_back(i);a[i]--;dfs(pos + 1);a[i]++;path.pop_back();}
}int main()
{for (int i = 1; i <= 4; i++)cin >> a[i];cin >> m;while (m--){cin >> x >> y;vis[x][y] = vis[y][x] = true;}path.push_back(0); // 坐标0位置空出dfs(1);cout << ret << endl;return 0;
}

接雨水问题

解法:动态规划 + 双指针

问题:以某个柱子为例,如果求出当前柱子最多能够接多少雨水?

 

找左右最大值就简单使用动态规划进行预处理

class Solution
{
public:long long n, ret = 0;long long left[200010] = {0}, right[200010] = {0};long long maxWater(vector<int> &arr){n = arr.size();left[0] = arr[0];for (int i = 1; i < n; i++)left[i] = max(left[i - 1], (long long)arr[i]);right[n - 1] = arr[n - 1];for (int i = n - 2; i >= 0; i--)right[i] = max(right[i + 1], (long long)arr[i]);for (int i = 0; i < n; i++)ret += min(left[i], right[i]) - arr[i];return ret;}
};

Day6

疯狂的自我检索者

解法:模拟

简单模拟题

#include <iostream>
using namespace std;int n, m, tmp;
double ret1, ret2;int main()
{cin >> n >> m;for (int i = 0; i < n - m; i++){cin >> tmp;ret1 += tmp;ret2 += tmp;}for (int i = 0; i < m; i++){ret1 += 1;ret2 += 5;}printf("%f %f", ret1 / n, ret2 / n);return 0;
}

栈和排序

解法:栈和贪心

贪心策略:让栈里面的最大值尽可能地出栈

做法:定义最大值aim,遍历数组a时,遇到最大值进栈后就执行出栈操作,更新aim为次大值,如果次大值也在栈里面的话,就要把次大值及其以上的数从栈里面弹出,再次更新aim...直到aim值不再栈里面就往下遍历数组a...

问题:怎么知道最大值aim此时在栈里面?

使用数组vis进行标记,把进栈的值标记为true;

当找到最大值aim时先更新aim的值,在进行出栈操作

class Solution
{
public:vector<int> solve(vector<int> &a){vector<int> ret;stack<int> s;bool vis[50010] = {false};int n = a.size(), aim = n;for (auto &e : a){s.push(e);vis[e] = true;// 最大值进栈后,先更新下次要找的最大值while (vis[aim])aim--;// 把比下次要找的最大值大的元素出栈while (s.size() && s.top() >= aim){ret.push_back(s.top());s.pop();}}return ret;}
};

加减

解法:贪心 + 前缀和 + 滑动窗口(二分)

问题1:怎样才能快速找到两个值的操作次数最小?

        先排序,把接近相等的值依靠在一起;

然后就进行枚举所有区间,找出最小的操作次数的个数(但这里n^2超时),需要进行优化;

问题2:怎么计算一个区间内的最小操作次数?

        该问题转化为数学问题:在水平线上找一个位置,使得所有的点到该位置距离最小?

        结论:找中间值使得所有的点到该位置距离最小(证明略)

        根据该结论来推导一个区间的最小操作次数的公式:

        计算一个区间内的个数使用前缀和数组可以快速地计算出来;

        有了公式能够直接计算出某个区间的最小代价cost后,可以利用排序数组单调性的特点,使用滑动窗口O(N)快速找到某个区间是否合法,统计并找出最大区间

        同样可以枚举‘左端点’,通过二分算法找到’右端点’(这里的)统计并找出最大区间

#include <iostream>
#include <algorithm>
using namespace std;long long n, k, a[100010], sum[100010], SumK;
int ret = 1;long long GetSumK(int left, int right)
{int mid = (left + right) / 2;//     return (mid-left)*a[mid]-(sum[mid-1]-sum[left-1])+//             (sum[right]-sum[mid])-(right-mid)*a[mid];return (mid - left - right + mid) * a[mid] - (sum[mid - 1] - sum[left - 1]) +(sum[right] - sum[mid]);
}int main()
{cin >> n >> k;for (int i = 1; i <= n; i++)cin >> a[i];sort(a, a + n + 1);for (int i = 1; i <= n; i++)sum[i] = a[i] + sum[i - 1];// 二分for (int i = 1; i <= n; i++){int left = i, right = n;// 枚举i的‘右端点’:其实不是真的右端点,而是left和right的中间值aim// 看看【i,aim】区间是否合法while (left < right){int aim = (left + right + 1) / 2;if (GetSumK(i, aim) <= k){left = aim;}elseright = aim - 1;}ret = max(ret, left - i + 1);}// 滑动窗口//     for(int left=1,right=1;right<=n;right++)//     {//         SumK=GetSumK(left, right);//         while(SumK > k)//         {//             left++;//             SumK=GetSumK(left, right);//         }//         ret=max(ret,right-left+1);//     }cout << ret << endl;return 0;
}

以上便是全部内容,有问题欢迎在评论区指正,感谢观看!

http://www.dtcms.com/wzjs/102175.html

相关文章:

  • 营销网站制作企业电商平台怎么注册
  • 天津武清做淘宝网站电商运营自学网站
  • 长春标准网站建设seo营销推广服务公司
  • xp系统中做网站服务器吗百度引流推广怎么做
  • wordpress 头像上传西安seo优化顾问
  • 如何网上做任务赚钱的网站百度优化关键词
  • 出口外贸网站泉州关键词优化软件
  • 常用网站开发工具搜索引擎优化方法总结
  • 极简主题wordpressseo专员简历
  • Ag网站制作广州排前三的seo公司
  • 吉林省建设信息网站长尾关键词挖掘站长工具
  • 中秋网页设计素材网站建立营销型网站
  • 济南网站建设599学生个人网页制作html代码
  • 有哪些学做衣服的网站seo的基本步骤顺序正确的是
  • 上海好的高端网站建设百度关键词排名代发
  • 花店网站建设构思如何做百度推广
  • 视频背景做网站背景湖南网站建设推广优化
  • 哪个网站可以做免费宣传网络平台怎么推广
  • 云服务器网站建设市场营销策划方案范文
  • 云平台开发网站手机百度下载安装
  • dreamweaver 个人网站seo网站有哪些
  • 南宁网站建设建站系统百度贴吧怎么发广告
  • 自己做企业网站好做吗外链是什么意思
  • 织梦做的网站怎么样查关键词排名软件
  • 群晖安装 wordpress裤子seo标题优化关键词
  • 网站套餐报价免费发外链的网站
  • wordpress 插件查看兰州seo优化公司
  • WordPress 文章 内容 滚动seo是广告投放吗
  • 如何建设公司网站 需要注意什么可以免费推广的网站
  • 网站弹窗页面是谁做的厦门人才网招聘官网