IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 2021牛客暑期多校训练营1 部分题解 -> 正文阅读

[数据结构与算法]2021牛客暑期多校训练营1 部分题解

2021牛客暑期多校训练营1

A: Alice and Bob

解释

暴力打表,由必败状态确定必胜状态。

结论:对于第有一堆为i大小的石头,存在最多一堆为j的石头为必败状态。

证明:设当前有两堆(i,p),(i,q),q > p,且为后手必胜状态。那么将(i,q)拿走(0,q-p)个后变成(i,p),那么(i,q)应该为先手必胜,故与假设矛盾。

那么枚举(i,j),当这个为必败状态时扩展这个点。复杂度O( n 2 l o g n n^2logn n2logn) .

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;
const int mod = 1e9 + 7;
const double eps = 1e-9;
typedef long long ll;
//#define int long long

bool f[N][N];

void get(){
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			if(f[i][j] == 0){
				for(int k=1;i+k<N;k++)
					for(int s=0;s*k+j<N;s++)
						f[i+k][j+s*k] = 1;
				for(int k=1;j+k<N;k++)
					for(int s=0;s*k+i<N;s++)
						f[i+s*k][j+k] = 1;
			}
}

signed main(){
    IOS
	get();
	int tt; cin>>tt;
	while(tt --){
		int n,m; cin>>n>>m;
		if(f[n][m]) cout<<"Alice"<<endl;
		else cout<<"Bob"<<endl;
	}
    
    return 0;
}

B: Ball Dropping

解释

请添加图片描述

Δ E G H ~ Δ D F C \Delta{EGH}\sim \Delta{DFC} ΔEGHΔDFC E G D F = E H D C \frac{EG}{DF} = \frac{EH}{DC} DFEG?=DCEH? Δ D J H ~ Δ D F C \Delta{DJH} \sim \Delta{DFC} ΔDJHΔDFC D J D F = J H F C \frac{DJ}{DF} = \frac{JH}{FC} DFDJ?=FCJH? 即可以得到 D J DJ DJ m m m 的高度。

那么 E H = r × h 2 + ( a ? b 2 ) 2 h EH = \frac{r\times\sqrt{h^2+(\frac{a-b}{2})^2}}{h} EH=hr×h2+(2a?b?)2 ?? D J = E H ? b 2 a ? b 2 × h DJ = \frac{EH-\frac{b}{2}}{\frac{a-b}{2}}\times h DJ=2a?b?EH?2b??×h

b > 2 ? r b > 2*r b>2?r 时,上述不成立,即为Drop.

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-7;
#define C(x) ((x)*(x))

signed main(){
    IOS
    long double r,a,b,h; cin>>r>>a>>b>>h;
	long double EH = r*sqrt(C(h)+C((a-b)/2)) / h;
	long double DJ = (EH - b/2) / ((a-b)/2) * h;
    if(b > 2 * r) cout<<"Drop"<<endl;
    else {
    	cout<<"Stuck"<<endl;
    	cout<<fixed<<setprecision(7)<<DJ<<endl;
	}
    return 0;
}

D: Determine the Photo Position

解释

统计每一行中连续0的个数,每一行分别处理

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;

string s[N];

signed main(){
    int n,k; cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>s[i];
	cin>>s[n+1];
	int cnt = 0,ans = 0;
	for(int i=1;i<=n;i++){
		for(int j=0;j<n;j++){
			if(s[i][j] == '0'){
				cnt ++;
			}else{
				if(cnt >= k){
					ans += cnt - k + 1;
				}
				cnt = 0;
			}
		}
		if(cnt >= k) ans += cnt - k + 1;
		cnt = 0;
	}
    cout<<ans<<endl;
    
	return 0;
}

F: Find 3-friendly Integers

解释

大于等于100的一定包含3的倍数

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const double eps = 1e-9;
#define int long long

int slove(int x){
	int cnt = 0;
	for(int i=1;i<=x;i++){
		if(i % 3 == 0) cnt ++;
		else{
			if(i >= 10){
				if(i%10%3 == 0 || i/10 % 3 == 0) cnt ++;
			}
		}
	}
	return cnt;
}

signed main(){
	int tt; cin>>tt;
	while(tt --){
		int l,r; cin>>l>>r;
		int ll = min(l,99ll);
		int rr = min(r,99ll);
		cout<<slove(rr)+(r - rr) - slove(ll-1) - (l - ll)<<endl;
	}
	
	return 0;
}

G: Game of Swapping Numbers

解释

  1. a i , b i a_i,b_i ai?,bi? 看成一个区间,考虑交换所产生的值。
  2. 对于n > 2, b i ? a i < = 0 b_i-a_i <= 0 bi??ai?<=0 或者 b i ? a i = > 0 b_i-a_i => 0 bi??ai?=>0 都会出现两次 以上,则对于k次交换,可以取任意次拿来做无意义的交换。n=2特判。
  3. 下面是区间交换会产生的结果。

请添加图片描述

存下 m i n ( a i , b i ) , m a x ( a i , b i ) min(a_i,b_i),max(a_i,b_i) min(ai?,bi?)max(ai?,bi?)的值,排序,取尽可能大的值。那就要优先取 m i n ( a i , b i ) ? m a x ( a j , b j ) min(a_i,b_i)-max(a_j,b_j) min(ai?,bi?)?max(aj?,bj?) 最大的。

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;

int a[N],b[N],mi[N],ma[N];

signed main(){
	IOS
    int n,k; cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) ma[i] = max(a[i],b[i]),mi[i] = min(a[i],b[i]);
	int ans = 0;
    if(n == 2){
    	if(k % 2) swap(a[1],a[2]);
    	ans = abs(a[1]-b[1]) + abs(a[2]-b[2]);
	}else{
		sort(mi+1,mi+n+1);sort(ma+1,ma+n+1);
		reverse(mi+1,mi+n+1);
		for(int i=1;i<=n;i++) ans += abs(a[i]-b[i]);
		for(int i=1;i<=min(n,k);i++) if(mi[i] > ma[i]) ans += 2 * (mi[i] - ma[i]);
	}
    cout<<ans<<endl;
	return 0;
}

H: Hash Function

解释

由题目得出 ( a % m o d ≠ b % m o d ) = ( a ? b ) % m o d ≠ 0 (a\%mod \neq b\%mod) = (a-b)\%mod \neq 0 (a%mod?=b%mod)=(a?b)%mod?=0 即所有数的差值不能被mod整除, 对于求所有数的差值。暴力是 n 2 n^2 n2 ,可以用FFT/NNT加速多项式相乘求解。

为什么能用多项式?

  1. 假设x,y,z都是多项式,且为 k 1 × x 1 1 + k 2 × x 2 2 + . . . + k n × x n n k_1\times x_1^1 + k_2 \times x_2^2 + ... + k_n \times x_n^n k1?×x11?+k2?×x22?+...+kn?×xnn? 这种形式,下标与指数一一对应。

  2. 假设 k i k_i ki?表示 i 这个值是否出现在差值序列中, k i > = 1 k_i >= 1 ki?>=1 说明存在。

  3. c = a ? b = > p ( c ) = p ( a ? b ) = > p ( c ) = p ( a ) × p ( ? b ) c = a - b => p(c) = p(a-b) => p(c) = p(a) \times p(-b) c=a?b=>p(c)=p(a?b)=>p(c)=p(a)×p(?b) , p ( c ) 等 价 于 x c p(c) 等价于 x^c p(c)xc

  4. 多项式相乘后,x每一项都会和y所有项进行组合。相当于a中的所有数和其它的值求了差值,只是多项式表示是否存在。

  5. 构造两个多项式,对于每一个数,它对于差值的贡献为 a 和 -a,构造x和y两个多项式系数,初始化x的第a项系数为1,y的第-a项系数为1。

  6. 项数不存在负数,加一个偏移量P。

  7. FFT/NNT复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

  8. 最后得到的序列系数,第i位对应的值为,i - P 。从 大于等于 P开始枚举。

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 3e6 + 10;
typedef complex<double> CP;
const double Pi = acos(-1);
const int P = 500001;

CP a[N],b[N];
bool vis[N];

void FFT(CP *x,int lim,int inv){
   int bit = 1,m;
   CP stand,now,temp;
   while((1<<bit) < lim) ++bit;
   for(int i=0;i<lim;++i){
       m = 0;
       for(int j=0;j<bit;++j) if(i & (1<<j)) m |= (1<<(bit-j-1));
       if(i<m) swap(x[m],x[i]);
   }
   for(int len=2;len<=lim;len<<=1){
       m = len >> 1;
       stand = CP(cos(2*Pi/len),inv*sin(2*Pi/len));
       for(CP *p=x; p!=x+lim;p+=len){
           now = CP(1,0);
           for(int i=0;i<m;++i,now*=stand){
               temp = now * p[i+m];
               p[i+m] = p[i] - temp;
               p[i] = p[i] + temp;
           }
       }
   }
   if(inv == -1) for(int i=0;i<lim;++i) x[i].real(x[i].real()/lim);
}

bool check(int x){
   for(int i=x;i<=P;i+=x) if(vis[i] == 1) return 0;
   return 1;
}

signed main(){
	IOS
    int n; cin>>n;
    for(int i=1;i<=n;i++){
    	int x; cin>>x;
    	a[x].real(1);
    	b[P-x].real(1);
	}
	int m = 1 << 20; // 500000 转2进制为1 << 20 位 
	FFT(a,m,1); FFT(b,m,1);
	for(int i=0;i<m;i++) a[i] *= b[i];
	FFT(a,m,-1);
	for(int i=P;i<m;i++){
		int k = (int)(a[i].real() + 0.5);
		if(k > 0) vis[i-P] = true;
	}
	for(int i=n;;i++){
		if(check(i)){
			cout<<i<<endl;
			break;
		}
	}
	return 0;
}

I: Increasing Subsequence*

解释

代码

K: Knowledge Test about Match

解释

贪心策略,枚举每一个差值是否出现,出现则匹配。每次先放右边的数和先放左边的数不影响最后结果,因为题目数据保证随机的。根据数据范围n^2也能过,最多有40组数据等于1000。

sqrt函数性质,(部分小的差值+部分大的差值) 比 (中等大小的差值)优。

代码

#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e4 + 10;

int ans[N],cnt[N];

signed main(){
	int tt; cin>>tt;
	while(tt --){
		for(int i=0;i<=1000;i++) cnt[i] = 0,ans[i] = -1;
		int n; cin>>n;
		for(int i=1;i<=n;i++) {
			int x; cin>>x;
			cnt[x] ++;
		}
		for(int d=0;d<=n;d++)
			for(int i=0;i<n;i++){
				if(ans[i] != -1) continue;
				if(i+d < n && cnt[i+d]){
					ans[i] = i+d;
					cnt[i+d] --;
				}else if(i-d >= 0 && cnt[i-d]){
					ans[i] = i-d;
					cnt[i-d] --;
				}
			}
		for(int i=0;i<n;i++) cout<<ans[i]<<" ";
		cout<<endl;
	}
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:55:27  更:2021-07-25 11:55:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 2:46:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码