zoukankan      html  css  js  c++  java
  • 多校联合(5)

          比赛时看完了 4 5 6 题,第四题感觉是线段树,想等会儿让HG 写,5 题没看懂,是后来LM给我讲的,所以一开始一直在研究 6,等LM 跟HG的题都过了,6 的样例还是没出来,然后跟LM一起想,还是没思路,决定去看别的题了,最后HG说可能是置换群的题目,他说他正好刚刷过去,说让他想吧,比完赛一看确实是有关置换的,但我们还是没做出来,5 后来到是猜到了一点的意思,但是看了题解后我才知道自己是多么的无知,竟然想着用打表的方式过,比赛还是充分体现了自己没学到的很多,学到了不会用的也很多,多做多练思路是很有必有的

    下面都是比赛时过题较多的,做过的无视就可以了

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4341

    题意:给出一些点坐标,表示这个点上有物体价值为val,需要的时间为 tim,问在给定的时间内可以获得的最大价值,有一个限制,如果在一条线上的获取宝贝必须按顺序来

    思路:把给的点先进行排序,然后统计出斜率相同的,然后再重新处理价值和时间,在进行二维背包

    View Code
     1 #include <iostream>
     2 #include <string.h>
     3 #include <algorithm>
     4 #include <stack>
     5 #include <queue>
     6 #include <math.h>
     7 #include <stdlib.h>
     8 #include <stdio.h>
     9 #define N 210
    10 #define inf 100000000
    11 #define _clr(a,val) (memset(a,val,sizeof(a)))
    12 
    13 using namespace std;
    14 
    15 struct node
    16 {
    17     int x;
    18     int y;
    19     int val;
    20     int tim;
    21     int dis;
    22 }point[N];
    23 int val[N][N],tim[N][N];
    24 bool vis[N];
    25 int back[N][N];
    26 int dp[N * N];  
    27 bool cmp(node a,node b)
    28 {
    29     return a.dis < b.dis;
    30 }
    31 bool dist(node a,node b)
    32 {
    33     if(a.x * b.y == a.y * b.x) return true;
    34     else return false;
    35 }
    36 int main()
    37 {
    38     int i,j,k;
    39     int n,t;
    40     int cs = 0;
    41     //freopen("data.txt","r",stdin);
    42     while(scanf("%d%d",&n,&t) != EOF)
    43     {
    44         for(i = 0; i < n; i++)
    45         {
    46             scanf("%d%d%d%d",&point[i].x,&point[i].y,&point[i].tim,&point[i].val);
    47             point[i].dis = point[i].x * point[i].x + point[i].y * point[i].y;  // 排序时的参数
    48         }
    49         sort(point,point + n,cmp);
    50         _clr(vis,0);
    51         _clr(back,0);
    52         int num = 0;
    53         for(i = 0; i < n; i++)
    54         {
    55             if(!vis[i])
    56             {
    57                 num++; 
    58                 for(j = i; j < n; j++)
    59                 {
    60                     if(!vis[j])
    61                     {
    62                         if(dist(point[i],point[j]) == true)  // 统计斜率相同的点
    63                         {
    64                             vis[j] = true;
    65                             back[num][0]++;  // 保存个数
    66                             back[num][back[num][0]] = j;  // 保存第几个点
    67                         }
    68                     }
    69                 }
    70             }
    71         }
    72         for(i = 1; i <= num; i++)
    73         {
    74             val[i][0] = 0;
    75             tim[i][0] = 0;
    76             for(j = 1; j <= back[i][0]; j++)
    77             {
    78                 val[i][j] = val[i][j - 1] + point[back[i][j]].val;  // 重新计算价值和时间
    79                 tim[i][j] = tim[i][j - 1] + point[back[i][j]].tim;
    80             }
    81         }
    82         _clr(dp,0);
    83         for(i = 1; i <= num; i++)
    84         {
    85             for(j = t; j >= 0; j--)
    86             {
    87                 for(k = 0; k <= back[i][0]; k++)
    88                 {
    89                     if(j >= tim[i][k])
    90                     {
    91                         dp[j] = max(dp[j],(dp[j - tim[i][k]] + val[i][k]));  // 背包
    92                     }
    93                 }
    94             }
    95         }
    96         printf("Case %d: %d\n",++cs,dp[t]);
    97     }
    98     return 0;
    99 }

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4342

    题意:给一个n 让你求 第n个非平方数,并求出 从 1 到 n 的

     这个值,也就是 开方不大于 i 的正整数

    View Code
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <math.h>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 
     8 typedef long long ll;
     9 ll capow(ll x)
    10 {
    11     return x * x;
    12 }
    13 int main()
    14 {
    15     ll i,j;
    16     int t;
    17     ll n;
    18     //int n;
    19     //freopen("data.txt","r",stdin);
    20     scanf("%d",&t);
    21     while(t--)
    22     {
    23         cin>>n;
    24         i = 1;
    25         ll sum = 0;
    26         while(1)
    27         {
    28             if(n < capow(i + 1) - capow(i) - 1)
    29             break;
    30             else
    31             {
    32                 sum += (capow(i + 1) - capow(i)) * i;  // 根据给的公式,i 到 i + 1之间的数,除了 (i + 1) 开方 等于 (i + 1) 其他的都等于 i
    33                 n -= capow(i + 1) - capow(i) - 1;   //  (i + 1) 平方 到 i 平方之间的数全部为非平方数,这样不断的去降 n 
    34                 i++;
    35             }
    36         }
    37         int temp = i;
    38         if(n == 0)   
    39         {
    40             i = capow(i) - 1;
    41             cout<<i<<" "<<sum<<endl;
    42             continue;
    43         }
    44         else   // 处理n 没有恰好降到零
    45         {
    46             i = capow(i);
    47             while(n--)
    48             {
    49                 i++;
    50             }
    51         }
    52         ll tem = i;
    53         if(capow(temp + 1) > i)   // 处理剩余的没有加的数
    54         {
    55             tem = tem - capow(temp) + 1;
    56             sum += temp * tem;
    57         }
    58         cout<<i<<" "<<sum<<endl;
    59     }
    60     return 0;
    61 }

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4345

    这个本来就是看标程才懂的,所以还是贴别人的讲解吧     循环节的长度为各独立置换环长度的最小公倍数。问题即求相加和为N的正整数的最小公倍数的可能数。由于1不影响最小公倍数,问题转化为相加小于等于N的若干正整数的最小公倍数的可能数。 如果这些正整数包含大于一个质因子,只会使得正整数的和更大。 因而问题再次转化为相加小于等于N的若干质数的最小公倍数的可能数。  N<1000,于是可递推得,标程用记忆化搜索实现的。

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <string.h>
     4 #include <iostream>
     5 #define _clr(a,val) (memset(a,val,sizeof(a)))
     6 
     7 using namespace std;
     8 
     9 typedef long long ll;
    10 ll dp[210][1200];
    11 ll prim[210], num;
    12 int vis[1010];
    13 void is_prim(int n)
    14 {
    15     int i,j,k;
    16     for(i = 2; i <= n; i++)
    17     {
    18         if(vis[i] == 0)
    19         {
    20             prim[num ++] = i;
    21         }
    22         for(j = 0, k = i * prim[j]; j <= num && k <= n; j++,k = i * prim[j])
    23         {
    24             vis[k] = 1;
    25             if(i % prim[j] == 0) break;
    26         }
    27     }
    28 }
    29 ll cal(int x,int n)
    30 {
    31     if(x == num) return 1;
    32     if(dp[x][n] != -1) return dp[x][n];
    33     dp[x][n] = cal(x + 1,n);
    34     ll ans = prim[x];
    35     while(ans <= n)
    36     {
    37         dp[x][n] += cal(x + 1,n - ans);
    38         ans *= prim[x];
    39     }
    40     return dp[x][n];
    41 }
    42 int main()
    43 {
    44     int n;
    45     while(scanf("%d",&n) != EOF)
    46     {
    47         _clr(vis,0);
    48         num = 0;
    49         is_prim(n);
    50         _clr(dp,-1);
    51         cout<<cal(0,n)<<endl;
    52     }
    53     return 0;
    54 }

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4349

    思路:题解上是这样解释的本题为Lucas定理推导题,我们分析一下 C(n,m)%2,那么由lucas定理,我们可以写成二进制的形式观察,比如 n=1001101,m是从000000到1001101的枚举,我们知道在该定理中   C(0,1)=0,因此如果n=1001101的0对应位置的m二进制位为1那么C(n,m) % 2==0,因此m对应n为0的  位置只能填0,而1的位置填0,

    1都是1(C(1,0)=C(1,1)=1),不影响结果为奇数,并且保证不会出n的范围,因此所有的情况即是n中1位置对应m位置0,1的枚举,那么结果很明显就是:2^(n中1的个数)

    View Code
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <math.h>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 
     8 typedef long long ll;
     9 int main()
    10 {
    11     int i,j;
    12     ll sum;
    13     int n;
    14     while(scanf("%d",&n) != EOF)
    15     //while(cin>>n)
    16     {
    17         int num = 0;
    18         while(n)
    19         {
    20             if(n % 2) num ++;
    21             n /= 2;
    22         }
    23         sum = pow(2,num);
    24         printf("%I64d\n",sum);
    25         //cout<<sum<<endl;
    26     }
    27     return 0;
    28 }

     

  • 相关阅读:
    Windows10如何删除“极速输入法”?
    python 递归实现 冒泡排序
    leetcode 912
    python 快速排序
    python 选择排序
    python 使用递归法对整数进行因数分解
    用函数嵌套定义和递归实现帕斯卡公式C(n,i) = C(n-1, i) + C(n-1, i-1), 进行组合数C(n,i)的快速求解。
    L2-3 清点代码库 (25 分)- 2021 天梯赛
    L2-2 病毒溯源 (25 分)
    快速幂
  • 原文地址:https://www.cnblogs.com/fxh19911107/p/2628918.html
Copyright © 2011-2022 走看看