• 牛客多校赛2(找规律/根号分块 三维括号dp)


    G-Link with Monotonic Subsequence

    题意:

    让max(最长上升子序列个数,最长下降子序列个数)最小

    思路:

    通过不停不停地找规律得出按照根号分块最好

    注意:

    比赛的时候把题目想复杂了,以为要不断递归分块呜呜呜

    代码:

    1. #include
    2. using namespace std;
    3. int main()
    4. {
    5. ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    6. int T;cin>>T;
    7. while(T--){
    8. int n;cin>>n;
    9. double m;m=sqrt(n);int k=ceil(m);
    10. for(int i=k;i>=1;i--){
    11. for(int j=i;j<=n;j+=k)cout<' ';
    12. }
    13. cout<<'\n';
    14. }
    15. return 0;
    16. }

    K-Link with Bracket Sequence I

    题意:

    给定一个具有  长度的括号序列  s ,并且给定一个整数  m ,序列 s  是长度为  的括号序列  的子序列。求合法的括号序列的数量

    思路:

    f[i][j][k]表示在序列b的第i个字符,与s的最长公共子序列为j,当前的新串左括号比右括号多k个(不允许左括号比右括号少)情况下的方案数。

    1 s[j]是左括号

    1.1 b[i]的位置放入s[j]  前提k-1≥0

      f[i][j][k] = (f[i][j][k] + f[i-1[j-1][k-1]) % mod;

    1.2 b[i]的位置放入s[j],而是放入右括号 

      f[i][j][k] = (f[i][j][k] + f[i - 1][j][k + 1]) % mod;

    注意:

    0.记得dp[0][0][0]=1

    1.记得初始化!要初始化是因为动态转移方程式中是根据 s[ j ] 是左括号还是右括号来进行判断的,所以当不放入子序列的时候,也就是j=0时,要遍历i和k进行状态转移

    2.内存不要开太大!三位dp的话,dp[250][250][250]会TLE,所以dp[205][205][205]刚好

    代码:

    1. #include
    2. using namespace std;
    3. int dp[205][205][205];//在总序列的第几个 子序列的第几个 左括号比右括号多几个
    4. const int mod=1e9+7;
    5. int main()
    6. {
    7. int T;cin>>T;int n,m;char s[250];
    8. while(T--){
    9. memset(dp,0,sizeof(dp));
    10. cin>>n>>m;cin>>s+1;
    11. dp[0][0][0]=1;
    12. for(int i=1;i<=m;i++)
    13. for(int k=0;k<=i;k++){
    14. dp[i][0][k]=(dp[i][0][k]+dp[i-1][0][k+1])%mod;//加入右括号
    15. if(k>=1)dp[i][0][k]=(dp[i][0][k]+dp[i-1][0][k-1])%mod;//加入左括号
    16. }
    17. for(int i=1;i<=m;i++){//在总序列的第几个
    18. for(int j=1;j<=min(i,n);j++){//子序列的第几个
    19. for(int k=0;k<=i;k++){//左括号比右括号多几个
    20. if(s[j]=='('){
    21. if(k>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-1][k-1])%mod;
    22. //把左括号放进来
    23. dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k+1])%mod;
    24. //不要左括号 加上右括号
    25. //注意这里的条件不同 所以要分开加
    26. }
    27. else if(s[j]==')'){
    28. dp[i][j][k]=(dp[i][j][k]+dp[i-1][j-1][k+1])%mod;
    29. if(k>=1) dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k-1])%mod;
    30. }
    31. }
    32. }
    33. }
    34. cout<0]<<'\n';
    35. }
    36. }

    J-Link with Arithmetic Progression

    题意:

    给n个数组,拟合y=kx+b 求拟合的方差最小值

    思路一:

    因为方差是平方和,所以用三分公差,之后每个ai减去当前的公差,得到n个首项。于是方差的求解变成了(首项i -指定的首项)的平方,从贪心的角度看,指定的首项是首项i的平均数时,方差会最小。

    注意:

    1.eps设为1e-10来保证精度

    2.如果不把double设为long double会运行超时

    代码:【1727ms】

    1. #include
    2. using namespace std;
    3. #define double long double
    4. #define eps 1e-10
    5. double a[100005],b[100005];int n;
    6. double f(double mid){
    7. double sum=0;
    8. for(int i=1;i<=n;i++){
    9. b[i]=a[i]-(i-1)*mid;
    10. sum=sum+b[i];
    11. }
    12. sum=sum/n;
    13. double ans=0;
    14. for(int i=1;i<=n;i++){
    15. ans=ans+(sum-b[i])*(sum-b[i]);
    16. }
    17. return ans;
    18. }
    19. int main()
    20. {
    21. ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    22. int T;cin>>T;
    23. while(T--){
    24. cin>>n;
    25. for(int i=1;i<=n;i++)cin>>a[i];
    26. double l=-1e9,r=1e9;
    27. while(l+eps
    28. double lmid=l+(r-l)/3.0,rmid=r-(r-l)/3.0;
    29. if(f(lmid)<f(rmid)) r=rmid;
    30. else l=lmid;
    31. }
    32. cout<setprecision(12)<<f(l)<<'\n';
    33. }
    34. return 0;
    35. }

    思路二:

    最小二乘法

    代码:【425ms】

    1. #include
    2. using namespace std;
    3. #define double long double
    4. #define int long long
    5. double a[100005],x1[100005],x2[100005];int n;
    6. signed main()
    7. {
    8. ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    9. int T;cin>>T;
    10. for(int i=1;i<=100000;i++){x1[i]=x1[i-1]+i;x2[i]=x2[i-1]+i*i;}
    11. while(T--){
    12. cin>>n;double y=0,xy=0; double aa,bb,ans=0;
    13. for(int i=1;i<=n;i++){cin>>a[i];y+=a[i];xy+=i*a[i];}
    14. aa=1.0*(x2[n]*y-x1[n]*xy)/(n*x2[n]-x1[n]*x1[n]);
    15. bb=1.0*(n*xy-x1[n]*y)/(n*x2[n]-x1[n]*x1[n]);
    16. for(int i=1;i<=n;i++)ans=ans+(a[i]-aa-bb*i)*(a[i]-aa-bb*i);
    17. cout<setprecision(12)<'\n';
    18. }
    19. return 0;
    20. }

    D-Link with Game Glitch

     题目:

    (讨论区题解的题目翻译) 

    小tips:

    spfa和dijkstra的算法区别

    SPFA模板代码:

    从源点开始,把每个遇上的点都放到队列里去。更新时,从队列里抓出来一个点x,点x指向点y,比较 从源点到点y的距离 从源点到点x 加上 从点x到点y的路径长度 更新最短的路径。

    1. vectormp[maxn];//用vector建立邻接表
    2. void Spfa(int s) {
    3. queue<int>v;
    4. vis[s] = 1; v.push(s); dis[s] = 0;
    5. while (!v.empty()) {
    6. int q = v.front();
    7. v.pop(); vis[q] = 0;
    8. for (int i = 0; i < mp[q].size(); i++) {
    9. if (dis[mp[q][i].s1] > dis[q] + mp[q][i].side) {
    10. dis[mp[q][i].s1] = dis[q] + mp[q][i].side;//更新最短路径。
    11. if (!vis[mp[q][i].s1]) {//是在更新新的值条件里面判断,一定特别注意这点
    12. v.push(mp[q][i].s1);
    13. vis[mp[q][i].s1] = 1;//标记未标记过的点
    14. }
    15. }
    16. }
    17. }
    18. }

     思路:

    若边权积大于1,则表示出现系统漏洞,因此用二分法确定w的大小。

    判断边权积大于1的话,讲边权积用log转换,再用spfa判断负环得到结果

    1. #include
    2. using namespace std;
    3. const int N = 1010;
    4. struct Edge { int u, v; double w; };
    5. vector edges, ed;
    6. int n, m;
    7. double dis[N];
    8. bool solve(double x) {
    9. ed.clear();
    10. for (auto e : edges) ed.push_back((Edge){e.u, e.v, log(e.w * x)});
    11. for (int i = 1; i <= n; ++i) dis[i] = -1e9;
    12. dis[1] = 0;
    13. for (int k = 1; k < n; ++k)for (auto e : ed) dis[e.v] = max(dis[e.v], dis[e.u] + e.w);
    14. for (auto e : ed)if (dis[e.v] < dis[e.u] + e.w) return false;
    15. return true;
    16. }
    17. int main()
    18. {
    19. scanf("%d%d", &n, &m);
    20. for (int i = 0; i < m; ++i) {
    21. int a, b, c, d;
    22. scanf("%d%d%d%d", &a, &b, &c, &d);
    23. edges.push_back((Edge){b, d, (1.0 * c) / a});
    24. }
    25. double L = 0, R = 1;
    26. while (L + 1e-7 < R) {
    27. double mid = (L + R) / 2;
    28. if (solve(mid)) L = mid; else R = mid;
    29. }
    30. printf("%.8f", L);
    31. return 0;
    32. }

  • 相关阅读:
    指针及其应用
    独立站定制开发,如何做Google广告引流
    c 理解创建多进程
    javascript 正则表达式匹配替换
    JWT(JSON Web Token)原理、使用方法及使用注意事项
    Flink系列之Flink 流式编程模式总结
    vmware中的linux虚拟机如何增加磁盘容量
    Jenkins CICD过程常见异常
    保姆级python安装教程
    langchain(1):使用LangChain 调用 openai 的 text/chat model
  • 原文地址:https://blog.csdn.net/zy98zy998/article/details/126546561