• 22/8/3(板子)树状dp板子+中国剩余定理+求组合数3,4+容斥原理


     

    目录

    1.树状dp--没有上司的舞会

    2. 中国剩余定理——表达整数的奇怪方式

    3. 求组合数3

     4.求组合数4

     5.满足条件的01序列(实质仍然是组合数)

    6.容斥原理--能被整除的数 


    有点多,但是都很重要,慢慢看

    1.树状dp--没有上司的舞会

    Ural 大学有 NN 名职员,编号为 1∼N1∼N。

    他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。

    每个职员有一个快乐指数,用整数 HiHi 给出,其中 1≤i≤N1≤i≤N。

    现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。

    在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。

    输入格式

    第一行一个整数 NN。

    接下来 NN 行,第 ii 行表示 ii 号职员的快乐指数 HiHi。

    接下来 N−1N−1 行,每行输入一对整数 L,KL,K,表示 KK 是 LL 的直接上司。

    输出格式

    输出最大的快乐指数。

    1. #include
    2. using namespace std;
    3. const int N=100010;
    4. bool if_happy[N];
    5. int he[N],ne[N],ed[N],idx;
    6. int happy[N];
    7. int f[N][3];
    8. void add(int a,int b)
    9. {
    10. ed[idx]=b;
    11. ne[idx]=he[a];
    12. he[a]=idx++;
    13. }
    14. void dfs(int u)
    15. {
    16. f[u][1]=happy[u];
    17. f[u][0]=0;
    18. for(int i=he[u];i!=-1;i=ne[i])
    19. {
    20. int j=ed[i];
    21. dfs(j);
    22. f[u][0]+=max(f[j][1],f[j][0]);
    23. //cout<
    24. f[u][1]+=f[j][0];
    25. }
    26. }
    27. int main()
    28. {
    29. int n,i,root,a,b;
    30. scanf("%d",&n);
    31. for(i=1;i<=n;i++)
    32. scanf("%d",&happy[i]);
    33. memset(he,-1,sizeof(he));
    34. for(i=1;i<=n-1;i++)
    35. {
    36. scanf("%d%d",&a,&b);
    37. add(b,a);
    38. if_happy[a]=true;
    39. }
    40. for(i=1;i<=n;i++)
    41. {
    42. if(if_happy[i]==false)
    43. {
    44. root=i;
    45. break;
    46. }
    47. }
    48. dfs(root);
    49. printf("%d\n",max(f[root][0],f[root][1]));
    50. return 0;
    51. }

    2. 中国剩余定理——表达整数的奇怪方式

    给定 2n2n 个整数 a1,a2,…,ana1,a2,…,an 和 m1,m2,…,mnm1,m2,…,mn,求一个最小的非负整数 xx,满足 ∀i∈[1,n],x≡mi(mod ai)∀i∈[1,n],x≡mi(mod ai)。

    输入格式

    第 11 行包含整数 nn。

    第 2…n+12…n+1 行:每 i+1i+1 行包含两个整数 aiai 和 mimi,数之间用空格隔开。

    输出格式

    输出最小非负整数 xx,如果 xx 不存在,则输出 −1−1。
    如果存在 xx,则数据保证 xx 一定在 6464 位整数范围内。

    1. #include
    2. #include
    3. using namespace std;
    4. typedef long long LL;
    5. LL exgcd(LL a, LL b, LL &x, LL &y)
    6. {
    7. if (!b)
    8. {
    9. x = 1, y = 0;
    10. return a;
    11. }
    12. LL d = exgcd(b, a % b, y, x);
    13. y -= a / b * x;
    14. return d;
    15. }
    16. int main()
    17. {
    18. int n;
    19. cin >> n;
    20. LL x = 0, m1, a1;
    21. cin >> m1 >> a1;
    22. for (int i = 0; i < n - 1; i ++ )
    23. {
    24. LL m2, a2;
    25. cin >> m2 >> a2;
    26. LL k1, k2;
    27. LL d = exgcd(m1, m2, k1, k2);
    28. if ((a2 - a1) % d)
    29. {
    30. x = -1;
    31. break;
    32. }
    33. k1 *= (a2 - a1) / d;
    34. k1 = (k1 % (m2/d) + m2/d) % (m2/d);
    35. x = k1 * m1 + a1;
    36. LL m = abs(m1 / d * m2);
    37. a1 = k1 * m1 + a1;
    38. m1 = m;
    39. }
    40. if (x != -1) x = (a1 % m1 + m1) % m1;
    41. cout << x << endl;
    42. return 0;
    43. }

    3. 求组合数3

    给定 nn 组询问,每组询问给定三个整数 a,b,pa,b,p,其中 pp 是质数,请你输出 CbamodpCabmodp 的值。

    输入格式

    第一行包含整数 nn。

    接下来 nn 行,每行包含一组 a,b,pa,b,p。

    输出格式

    共 nn 行,每行输出一个询问的解。

    数据范围

    1≤n≤201≤n≤20,
    1≤b≤a≤10181≤b≤a≤1018,
    1≤p≤1051≤p≤105,

     

    1. #include
    2. #include
    3. using namespace std;
    4. typedef long long LL;
    5. int qmi(int a, int k, int p)
    6. {
    7. int res = 1;
    8. while (k)
    9. {
    10. if (k & 1) res = (LL)res * a % p;
    11. a = (LL)a * a % p;
    12. k >>= 1;
    13. }
    14. return res;
    15. }
    16. int C(int a, int b, int p)
    17. {
    18. if (b > a) return 0;
    19. int res = 1;
    20. for (int i = 1, j = a; i <= b; i ++, j -- )
    21. {
    22. res = (LL)res * j % p;
    23. res = (LL)res * qmi(i, p - 2, p) % p;
    24. }
    25. return res;
    26. }
    27. int lucas(LL a, LL b, int p)
    28. {
    29. if (a < p && b < p) return C(a, b, p);
    30. return (LL)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
    31. }
    32. int main()
    33. {
    34. int n;
    35. cin >> n;
    36. while (n -- )
    37. {
    38. LL a, b;
    39. int p;
    40. cin >> a >> b >> p;
    41. cout << lucas(a, b, p) << endl;
    42. }
    43. return 0;
    44. }

     4.求组合数4

    输入 a,ba,b,求 CbaCab 的值。

    注意结果可能很大,需要使用高精度计算。

    输入格式

    共一行,包含两个整数 aa 和 bb。

    输出格式

    共一行,输出 CbaCab 的值。

    数据范围

    1≤b≤a≤50001≤b≤a≤5000

    输入样例:

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N = 5010;
    6. int primes[N], cnt;
    7. int sum[N];
    8. bool st[N];
    9. void get_primes(int n)
    10. {
    11. for (int i = 2; i <= n; i ++ )
    12. {
    13. if (!st[i]) primes[cnt ++ ] = i;
    14. for (int j = 0; primes[j] <= n / i; j ++ )
    15. {
    16. st[primes[j] * i] = true;
    17. if (i % primes[j] == 0) break;
    18. }
    19. }
    20. }
    21. int get(int n, int p)
    22. {
    23. int res = 0;
    24. while (n)
    25. {
    26. res += n / p;
    27. n /= p;
    28. }
    29. return res;
    30. }
    31. vector<int> mul(vector<int> a, int b)
    32. {
    33. vector<int> c;
    34. int t = 0;
    35. for (int i = 0; i < a.size(); i ++ )
    36. {
    37. t += a[i] * b;
    38. c.push_back(t % 10);
    39. t /= 10;
    40. }
    41. while (t)
    42. {
    43. c.push_back(t % 10);
    44. t /= 10;
    45. }
    46. return c;
    47. }
    48. int main()
    49. {
    50. int a, b;
    51. cin >> a >> b;
    52. get_primes(a);
    53. for (int i = 0; i < cnt; i ++ )
    54. {
    55. int p = primes[i];
    56. sum[i] = get(a, p) - get(a - b, p) - get(b, p);
    57. }
    58. vector<int> res;
    59. res.push_back(1);
    60. for (int i = 0; i < cnt; i ++ )
    61. for (int j = 0; j < sum[i]; j ++ )
    62. res = mul(res, primes[i]);
    63. for (int i = res.size() - 1; i >= 0; i -- ) printf("%d", res[i]);
    64. puts("");
    65. return 0;
    66. }

             5.满足条件的01序列(实质仍然是组合数)

    这个得说道说道,思路是将问题转化成一张图,0是向右走,1是向上走,求合法的路径数

    给定 nn 个 00 和 nn 个 11,它们将按照某种顺序排成长度为 2n2n 的序列,求它们能排列成的所有序列中,能够满足任意前缀序列中 00 的个数都不少于 11 的个数的序列有多少个。

    输出的答案对 109+7109+7 取模。

    输入格式

    共一行,包含整数 nn。

    输出格式

    共一行,包含一个整数,表示答案。

    数据范围

    1≤n≤1051≤n≤105

    输入样例:

    3
    

    输出样例:

    5
    1. #include
    2. #include
    3. using namespace std;
    4. typedef long long LL;
    5. const int N = 100010, mod = 1e9 + 7;
    6. int qmi(int a, int k, int p)
    7. {
    8. int res = 1;
    9. while (k)
    10. {
    11. if (k & 1) res = (LL)res * a % p;
    12. a = (LL)a * a % p;
    13. k >>= 1;
    14. }
    15. return res;
    16. }
    17. int main()
    18. {
    19. int n;
    20. cin >> n;
    21. int a = n * 2, b = n;
    22. int res = 1;
    23. for (int i = a; i > a - b; i -- ) res = (LL)res * i % mod;
    24. for (int i = 1; i <= b; i ++ ) res = (LL)res * qmi(i, mod - 2, mod) % mod;
    25. res = (LL)res * qmi(n + 1, mod - 2, mod) % mod;
    26. cout << res << endl;
    27. return 0;
    28. }

    6.容斥原理--能被整除的数 

    很巧妙的思想,多看看

    给定一个整数 nn 和 mm 个不同的质数 p1,p2,…,pmp1,p2,…,pm。

    请你求出 1∼n1∼n 中能被 p1,p2,…,pmp1,p2,…,pm 中的至少一个数整除的整数有多少个。

    输入格式

    第一行包含整数 nn 和 mm。

    第二行包含 mm 个质数。

    输出格式

    输出一个整数,表示满足条件的整数的个数。

    数据范围

    1≤m≤161≤m≤16,
    1≤n,pi≤1091≤n,pi≤109

    输入样例:

    1. 10 2
    2. 2 3

    输出样例:

    7
    
    1. #include
    2. using namespace std;
    3. typedef long long int LL;
    4. const int N = 20;
    5. int p[N];
    6. int main()
    7. {
    8. int n, m;
    9. cin >> n >> m;
    10. for (int i = 0; i < m; i++)
    11. cin >> p[i];
    12. int res = 0;
    13. for (int i = 1; i < 1 << m; i++)
    14. {
    15. int t = 1, s = 0;
    16. for (int j = 0; j < m; j++)
    17. {
    18. if (i >> j & 1)
    19. {
    20. if ((LL)t * p[j] > n)
    21. {
    22. t = -1;
    23. break;
    24. }
    25. t *= p[j];
    26. s++;
    27. }
    28. }
    29. if (t != -1)
    30. {
    31. if (s % 2)
    32. res += n / t;
    33. else
    34. res -= n / t;
    35. }
    36. }
    37. cout << res << endl;
    38. return 0;
    39. }

    明天上午学博弈论和记忆化搜索

  • 相关阅读:
    Linux的基本权限
    NX二次开发-ufusr和ufsta等用户入口使用说明
    用sqlyog远程连接LINUX系统的MYSQL出现错解决方法
    简单了解下最近正火的SwissTable
    你的GPU能跑Llama 2等大模型吗?用这个开源项目上手测一测
    精品SpringCloud的高校招生信息管理系统-微服务分布式
    Oracle数据库字符集概述及修改方式
    Java手写IOC
    为什么TCP握手刚刚好是3次呢?
    【Coppeliasim】 通过TCP与coppeliasim通信
  • 原文地址:https://blog.csdn.net/weixin_62848089/article/details/126148639