2021牛客寒假算法基础集训营6

题目链接

2021牛客寒假算法基础集训营6

F.组合数问题

题目描述

M 很喜欢组合数。
Z给了她一个数 n ( n 为偶数) ,让她计算 (n0)+(n2)+(n4)..+(nn) ,小 M 一下就秒掉了,觉得题好简单。
因此,小Z给了她一个难题: 给定一个数 n ( n4的倍数),计算 (n0)+(n4)+(n8)++(nn) ,答案对 998244353 取模。
M 不会做,请你来帮帮她吧!

输入描述:

输入一个数 n

输出描述:

输出答案对 998244353 取模的值。

解题思路

数论,复数快速幂

S1=(1+1)n+(11)n=2((n0)+(n2)++(nn))S2=(1+i)n+(1i)n=2((n0)(n2)++(nn))S1+S2=4((n0)+(n4)++(nn)) 所以原式 =2n+(1+i)n+(1i)n4 ,用复数快速幂即可 

  • 时间复杂度:O(logn)

代码

// Problem: 组合数问题 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/31272/F // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> // #define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int mod=998244353; LL n; struct Complex { LL x,y; Complex(LL _x,LL _y) { x=_x,y=_y; } }; void mul(Complex &a,Complex b,int p) { LL x=((a.x*b.x-a.y*b.y)%p+p)%p; LL y=((a.x*b.y+a.y*b.x)%p+p)%p; a={x,y}; } void add(Complex &a,Complex b,int p) { a.x=(a.x+b.x)%p; a.y=(a.y+b.y)%p; } Complex ksm(Complex a,LL b,int p) { Complex res(1,0); while(b) { if(b&1)mul(res,a,p); mul(a,a,p); b>>=1; } return res; } int ksm(int a,int b,int p) { int res=1; while(b) { if(b&1) res=1ll*res*a%p; a=1ll*a*a%p; b>>=1; } return res; } int main() { cin>>n; auto res=ksm({2,0},n,mod); add(res,ksm({1,1},n,mod),mod),add(res,ksm({1,-1},n,mod),mod); mul(res,ksm({4,0},mod-2,mod),mod); cout<<res.x; return 0; }

G.机器人

题目描述

题目描述

n 个机器人,每个机器人会读入一个 x ,并返回 ax+b

现在银临姐姐手里有一个数 x ,她想将机器人按某种顺序排列,使得最终返回得到的 x 尽可能大。

但是计算量太大啦,请你编个程序帮帮她吧。

输入描述:

第一行读入 n,x ,接下来 n 行依次输入 ai,bi

输出描述:

输出最大值。

示例1

输入

2 2 11 4 5 14

输出

268

备注:

对于所有的数据,1n,x,ai,bi20

解题思路

贪心

只考虑两个机器人的话,有这样的顺序:(ai,bi),(aj,bj),则有:aj×(aix+bi)+bjai×(ajx+bj)+bi,即 aibj+biajbi+bj,对于多个机器人,如果存在相邻两项不满足这样的关系,则交换后会更优,另外注意会爆long long

  • 时间复杂度:O(nlogn)

状压dp

  • 状态表示:f[i] 表示选择状态为 i 时的最大值

  • 状态计算:f[j]=max(f[j],f[i]a[t].fi+a[t].se),可以转移当且仅当 ji 在某位 t 上多一

  • 时间复杂度:O(n×2n)

代码

  • 贪心
// Problem: 机器人 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/31272/G // Memory Limit: 1048576 MB // Time Limit: 6000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } template <typename T> void print(T x) { if (x < 0) putchar('-'), x = -x; if (x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } int n; __int128 x; PII a[25]; int main() { cin>>n; read(x); for(int i=1;i<=n;i++)cin>>a[i].fi>>a[i].se; sort(a+1,a+1+n,[](PII &x,PII &y){return y.se*x.fi+x.se<x.se*y.fi+y.se;}); for(int i=1;i<=n;i++) x=x*a[i].fi+a[i].se; print(x); return 0; }
  • 状压dp
// Problem: 机器人 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/9986/G // Memory Limit: 1048576 MB // Time Limit: 6000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } template <typename T> void print(T x) { if (x < 0) putchar('-'), x = -x; if (x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } const int N=1<<21; __int128 f[N]; int n,x,b[N]; PII a[25]; int main() { cin>>n>>x; f[0]=x; for(int i=0;i<n;i++)cin>>a[i].fi>>a[i].se; for(int i=0;i<=n;i++)b[1<<i]=i; for(int i=0;i<=(1<<n)-1;i++) { int t=i^((1<<n)-1); while(t) { int tt=b[t&-t]; f[i|(t&-t)]=max(f[i|(t&-t)],f[i]*a[tt].fi+a[tt].se); t-=t&-t; } } print(f[(1<<n)-1]); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16069804.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示