Solved |
A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
4/12 |
O |
- |
- |
Ø |
- |
- |
- |
O |
- |
- |
- |
Ø |
题目链接
https://codeforces.com/gym/102798
Problem A. Golden Spirit
题意:
桥两边都有 $n$ 个人,每个人都需要过桥,休息 $x$ 分钟,再返回,每次过桥需要 $t$ 分钟。
所有人都只能在你的帮助下才能过桥,求最少需要多少分钟。
思路:
在返回前我们先将所有人都搬到对面,然后只有两个选择:
- 将当前边第一个休息好的人返回。
- 走到对面,将对面第一个休息好的人返回。
显然只要等完你选择的开始的一边的第一个人休息好,接下来可以无需等待,将所有人原路返回。
两种情况取最小值即可。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<LL> VLL; typedef vector<PII> VPII;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T;cin>>T; while(T--) { LL n,x,t;cin>>n>>x>>t; cout<<min(max(2*n*t,2*t+x),max((2*n+1)*t,t+x))+2*n*t<<'\n'; } return 0; }
|
Problem D. ABC Conjecture
题意:
对于 $a,b,c$,满足:
- $a,b$ 互质。
- $a+b=c$。
- $c>rad(abc)^{1+\epsilon}$。
$rad(n)=\prod_{p\mid n,p\in Prime}{p}$。
$T$ $(1\le T\le 10)$ 次询问,每次询问 $c$ $(1\le c\le 1e18)$,求是否存在 $a,b$ 使不等式成立。
思路:
当 $c$ 的惟一分解中存在质数因子的平方时,不等式成立。
pollard_rho 大数因式分解模板。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<LL> VLL; typedef vector<PII> VPII;
LL qmul(LL a,LL b,LL m) { LL ret=0; while(b) { if(b&1) ret=(ret+a)%m; a=(a+a)%m; b>>=1; } return ret; } LL qpow(LL a,LL b,LL m) { LL ret=1; while(b) { if(b&1) ret=qmul(ret,a,m); a=qmul(a,a,m); b>>=1; } return ret; } bool check(LL a,LL n) { if(n==2) return true; if(n==1||!(n&1)) return false; LL d=n-1; while(!(d&1)) d>>=1; LL t=qpow(a,d,n); while(d!=n-1&&t!=1&&t!=n-1) { t=qmul(t,t,n); d<<=1; } return t==n-1||d&1; } bool miller_rabin(LL n) { static vector<LL> P={2,325,9375,28178,450775,9780504,1795265022}; if(n<=1) return false; for(LL x:P) { if(x>n) break; if(!check(x,n)) return false; } return true; } mt19937 mt(time(0)); LL pollard_rho(LL n,LL c) { LL x=uniform_int_distribution<LL>(1,n-1)(mt),y=x; auto f=[&](LL v) { LL t=qmul(v,v,n)+c; return t<n?t:t-n; }; while(1) { x=f(x),y=f(f(y)); if(x==y) return n; LL d=__gcd(abs(x-y),n); if(d!=1) return d; } } VI fac; void get_fac(LL n,LL cc=19260817) { if(n==4) {fac.PB(2),fac.PB(2);return;} if(miller_rabin(n)) {fac.PB(n);return;} LL p=n; while(p==n) p=pollard_rho(n,--cc); get_fac(p),get_fac(n/p); } bool go_fac(LL n) { fac.clear(); if(n<=1) return false; get_fac(n); int sz=SZ(fac); sort(ALL(fac)); fac.resize(unique(ALL(fac))-fac.begin()); return SZ(fac)<sz; }
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T;cin>>T; while(T--) { LL n;cin>>n; cout<<(go_fac(n)?"yes":"no")<<'\n'; } return 0; }
|
Problem H. Message Bomb
题意:
$n$ $(n\le 1e5)$ 个组,$m$ $(m\le 2e5)$ 个人,$s$ $(n\le 2e6)$ 个操作:
- $t=1$,学生 $x$ 进入 $y$ 组。
- $t=2$,学生 $x$ 退出 $y$ 组。
- $t=3$,学生 $x$ 向 $y$ 组其他学生发送一条消息。
求每个学生收到多少条消息。
思路:
每组是独立的,按组分别计算贡献,记录进入的时间。
因为学生退出后可能再次进入,所以在退出时要加上贡献。
做完每一组的所有操作后对还在组内的学生加上贡献。
贡献可以用前缀和 $O(1)$ 计算,显然时间复杂度是线性的。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<LL> VLL; typedef vector<PII> VPII;
const int N=1e6+5; int sum[N],cnt[N],res[N]; VPII a[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n,m,s;cin>>n>>m>>s; for(int i=1;i<=s;i++) { int t,x,y;cin>>t>>x>>y; a[y].EB(t,x); } for(int i=1;i<=n;i++) { unordered_map<int,int> bg; sum[0]=0; for(int j=0;j<SZ(a[i]);j++) { int t=a[i][j].FI,x=a[i][j].SE; if(j) sum[j]=sum[j-1]; if(t==1) bg[x]=j,cnt[x]=0; else if(t==2) res[x]+=sum[j]-sum[bg[x]]-cnt[x],cnt[x]=0,bg.erase(x); else ++cnt[x],++sum[j]; } for(auto x:bg) res[x.FI]+=sum[SZ(a[i])-1]-sum[x.SE]-cnt[x.FI]; } for(int i=1;i<=m;i++) cout<<res[i]<<'\n'; return 0; }
|
Problem L. Clock Master
题意:
$T$ 次询问,把 $n$ 拆分为若干数的和,使得这些数的 $lcm$ 最大,输出 $\log(lcm)$。
$1\le T,n\le 30000$。
思路:
预处理出 $log$,将每个数拆为 $p^k$ 的形式,分组背包。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<LL> VLL; typedef vector<PII> VPII;
const int N=3e4+5; int mn[N]; VI p; DB lg[N],dp[N]; void prime_seive(int n) { for(int i=2;i<=n;i++) { if(!mn[i]) mn[i]=i,p.PB(i); for(auto x:p) { if(x>mn[i]||x*i>n) break; mn[i*x]=x; } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); prime_seive(30000); for(int i=1;i<=30000;i++) lg[i]=log(i); for(auto x:p) { for(int i=30000;i>=2;i--) { for(int j=x;i-j>=0;j*=x) { dp[i]=max(dp[i],dp[i-j]+lg[j]); } } } int T;cin>>T; while(T--) { int n;cin>>n; cout<<fixed<<setprecision(9)<<dp[n]<<'\n'; } return 0; }
|