第十八周 DMY 每日一题

目录

T1 最长公共子序列​编辑

 思路:

代码:

T2 喵喵序列

​思路:

代码:

T3 漂亮数

​思路:

代码:

T4 真假字符串

​思路:

代码:

T5 走不出的迷宫

​思路:

代码:

T6 最长同余子数组

 思路:

代码:

T7 互质

思路:

代码:

 T8 排队

​思路:

代码:

T9 最短路径计数

​思路:

代码:

T10 最后的舞会

思路:

代码:


T1 最长公共子序列

 思路:

采取离散化,将第一个排序利用map进行离散处理,如3对应1,2对应2,1对应3,4对应4,5对应5,然后在第二个排序就想到于求它的最长上升子序列。

代码:

#include<bits/stdc++.h>
using namespace std;
int a[100005], b[100005], mp[100005], c[100005];
int main()
{
	int n; cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		mp[a[i]] = i;
	}
	for (int i = 1; i <= n; i++)
	{
		cin >> b[i];
	}
	int len = 1;
	c[len] = mp[b[1]];
	for (int i = 2; i <= n; i++)
	{
		if (mp[b[i]] > c[len])
		{
			c[++len] = mp[b[i]];
		}
		else
		{
			*lower_bound(c + 1, c + 1 + len, mp[b[i]]) = mp[b[i]];
		}
	}
	cout << len << endl;
}

T2 喵喵序列

思路:

只要枚举中间的,然后利用分别在两边查找,在左边如果找到比中间小的数则L++,右边如果找到比中间大的数字则R++,则对于该中间的数字一共有L*R对满足条件,类似求最终总和

代码:

#include<bits/stdc++.h>
using namespace std;
long long a[30000];
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n; cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	long long ans = 0;
	for (int i = 2; i <= n - 1; i++)
	{
		long long  cnt1 = 0, cnt2 = 0;
		for (int j = 1; j < i; j++)
		{
			if (a[j] < a[i])
			{
				cnt1++;
			}
		}
		for (int j = i + 1; j <= n; j++)
		{
			if (a[j] > a[i])
			{
				cnt2++;
			}
		}
		ans += cnt1 * cnt2;
	}
	cout << ans << endl;
	return 0;
}

T3 漂亮数

 

思路:

只需要截取循环节,然后用该循环节构造相同位数的数字,然后再比较它和原本数字的大小,如果比原本的大的话则就是该数字,如果比它小的话只需要循环节加一再重新构造的那个数就是答案

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll n, k;
	string s;
	cin >> n >> k >> s;
	string s1 = s.substr(0, k);//取循环节
	string tmp_s = s1;
	while (tmp_s.size() <= n)
	{
		tmp_s += s1;//构造
	}
	ll len = s.size();
	bool tri = 0;
	for (ll i = 0; i < len; i++)//比较
	{
		if (s[i] == tmp_s[i])continue;
		else if (tmp_s[i] > s[i])break;//这里犯错了,如果新数比原数大就不要+1了
		else
		{
			tri = 1;
			break;
		}
	}
	if (tri == 1)//新数小于原数,让循环节+1
	{
		for (ll i = s1.size() - 1; i >= 0; i--)
		{
			if (s1[i] != '9')
			{
				s1[i] = char(s1[i] + 1);
				break;
			}
			else
			{
				s1[i] = '0';
				continue;
			}
		}
	}
	cout << n << endl;
	for (ll i = 0; i < n; i++)
	{
		cout << s1[i % k];//输出即可
	}
	return 0;
}

T4 真假字符串

 

思路:

首先,遍历一遍找到两个字符串的不同之处,然后再将不同的地方进行标记,如果没有不同的地方则说明这两个字符串相同,如果有的话,则让两个字符串分别删除这个点,将未删除的A和删除过后的B比较,同理用删除过后的A和未删除的B比较,然后再用双指针来找是否有不同的字符,如果有则删除之前未删除的字符串的该字符,再进行比较如果完全相同则满足条件,并且只要有一组满足条件即可

代码:

#include<bits/stdc++.h>
using namespace std;
bool check(string a, string b)//a是未删除之前的
{
	int l = 0, r = 0;
	while (l<a.size()&&r<b.size())
	{
		if (a[l] == b[r])
		{
			l++, r++;
		}
		else
		{
			a.erase(l, 1);
			if (a == b)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}
	return true;
}
int main()
{
	string a, b; cin >> a >> b;
	int now = -1;
	for (int i = 0; i < a.size(); i++)
	{
		if (a[i] != b[i])
		{
			now = i;
			break;
		}
	}
	if (now == -1)
	{
		cout << "1" << endl;
		return 0;
	}
	else
	{
		string s1 = a, s2 = b;
		s1.erase(now, 1);
		s2.erase(now, 1);
		if (check(a, s2) || check(b, s1))
		{
			cout << "1" << endl;
		}
		else
		{
			cout << "0" << endl;
		}
	}
	return 0;
}

T5 走不出的迷宫

 

思路:

一道简单的BFS题,当然也可以用动态规划写

代码:

#include<bits/stdc++.h>
using namespace std;
bool mp[105][105];
bool vis[105][105];
int C[105][105];
pair<int, int >way[2] = { {0,1},{1,0} };
queue<pair < int, int > > Q;
int main()
{
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		string s;
		cin >> s;
		for (int j = 0; j < s.size(); j++)
		{
			if (s[j] == '#')
			{
				mp[i][j + 1] = 1;
			}
		}
	}
	Q.push(make_pair(1, 1));
	vis[1][1] = true;
	C[1][1] = 1;
	int ans = 1;
	while (!Q.empty())
	{
		int x = Q.front().first;
		int y = Q.front().second;
		Q.pop();
		for (int i = 0; i <= 1; i++)
		{
			int now_x = x + way[i].first;
			int now_y = y + way[i].second;
			if (now_x <= n && now_y <= m && !mp[now_x][now_y] && !vis[now_x][now_y])
			{
				vis[now_x][now_y] = 1;
				Q.push(make_pair(now_x, now_y));
				C[now_x][now_y] = C[x][y] + 1;
				ans = max(C[now_x][now_y], ans);
			}
		}
	}
	cout << ans << endl;
	return 0;
}

T6 最长同余子数组

 思路:

根据同余定理,只需要两者差值可以被一个数整除,比如1 5 7,差值是4 2,可以被2整除,这就是个同余数组了。这属于是一个结论记住就行,然后我们可以先进行预处理,求出两者的差值,

然后再用二分答案来找最大的子序列长度即可

代码:

#include<bits/stdc++.h>
using namespace std;
long long a[200005], b[200005];
int n;
long long gcd(long long x, long long y)
{
	if (x < y)return gcd(y, x);
	if (y == 0)return x;
	if (x % y == 0)return y;
	else
	{
		return gcd(y, x % y);
	}
}
bool check(long long mid)
{
	mid = mid - 1;
	for (int i = 1; i <= n -mid; i++)
	{
		long long yu = b[i];
		bool flag = 1;
		if (yu == 1)continue;
		for (int j = i + 1; j <= i +mid- 1; j++)
		{
			long long now = gcd(yu, b[j]);
			if (now !=1)
			{
				yu = now;
			}
			else
			{
				flag = false;
				break;
			}
		}
		if (flag)
		{
			return true;
		}
	}
	return false;
}
int main()
{
	 cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for (int i = 1; i < n; i++)
	{
		b[i] = abs(a[i + 1] - a[i]);
	}

	int l = 1, r = n;
	while (l<r)
	{
		int mid = (l + r + 1) / 2;
		if (check(mid))
		{
			l = mid;
		}
		else
		{
			r = mid - 1;
		}
	}
	cout << l << endl;
}

T7 互质

思路:

拆解所求范围内所有的质因数,然后剩下的因子便是答案,同时要注意用判断是否查找过来减少时间复杂度

代码:

#include<bits/stdc++.h>
using namespace std;
int n, m;
bool a[100005], b[100005], c[100005];
int mx[100005];
int main()
{
	cin >> n >> m;
	mx[1] = 1;
	for (int i = 2; i <= 100005; i++)
	{
		if (c[i])continue;
		for (int j = i * 2; j <= 100005; j += i)
		{
			c[j] = 1;
			mx[j] = i;
		}
		mx[i] = i;
	}
	for (int i = 1; i <= n; i++)
	{
		int tmp;
		cin >> tmp;
		if (a[tmp])continue;
		a[tmp] = 1;
		while (tmp != 1)
		{
			b[mx[tmp]] = 1;
			tmp /= mx[tmp];
		}
	}
	vector<int>ans;
	ans.push_back(1);
	for (int i = 2; i <= m; i++)
	{
		if (b[i] == 1 && c[i] == 0)
		{
			for (int j = i; j <= m; j += i)
			{
				a[j] = 1;
			}
		}
	}
	for (int i = 2; i <= m; i++)
	{
		if (a[i] == 0)ans.push_back(i);
	}
	cout << ans.size() << endl;
	for (int i = 0; i < ans.size(); i++)cout << ans[i] << endl;
	return 0;
}

 T8 排队

 

思路:

这道题要知道的东西还是挺多的,首先对于尴尬值来说,展开后可以发现要想尴尬值最小则2*a*b要最大,且如果两个数组相乘,有序的数组相乘会大于无序的数组相乘,所以我们现在要做的就是把一个数组对于另一个数组相对有序:两边数组第一大的在同一个位置,第三大的在同一个位置,第二大的在同一个位置(不是说数组必须有序,而是相对有序,则要求最少的步数则相当于求有多少逆序对,而求逆序对则可以用线段树求解

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e5 + 50, MOD = 1e8 - 7;
ll f[4 * N];
void revise(int k, int l, int r, int x)
{
	if (l == r)
	{
		f[k] += 1;
		return;
	}
	int m = (l + r) / 2;
	if (x <= m)revise(k + k, l, m, x);
	else revise(k + k + 1, m + 1, r, x);
	f[k] = (f[k + k] + f[k + k + 1]) % MOD;
}

ll calc(int k, int l, int r, int x, int y)
{
	if (l == x && y == r)
	{
		return f[k];
	}
	int m = (l + r) / 2;
	if (y <= m)return calc(k + k, l, m, x, y);
	else
		if (x > m)return calc(k + k + 1, m + 1, r, x, y);
		else return (calc(k + k, l, m, x, m) + calc(k + k + 1, m + 1, r, m + 1, y)) % MOD;
}

int main() {
	int n;
	cin >> n;
	vector<PII>a(n), b(n);
	for (int i = 0; i < n; i++)
	{
		cin >> a[i].first;
		a[i].second = i;
	}
	for (int i = 0; i < n; i++)
	{
		cin >> b[i].first;
		b[i].second = i;
	}
	sort(a.begin(), a.end());
	sort(b.begin(), b.end());
	vector<int>v(n);
	for (int i = 0; i < n; i++)
	{
		v[a[i].second] = b[i].second + 1;
	}
	ll res = 0;
	for (int i = n - 1; i >= 0; i--)
	{
		if (v[i] != 1)res = (res + calc(1, 1, n, 1, v[i] - 1)) % MOD;
		revise(1, 1, n, v[i]);
	}
	cout << res << endl;

	return 0;
}

T9 最短路径计数

 

思路:

利用BFS,每经过一个点进行标记,如果该点未被标记则将其标记并放入队内,同时定于深度数组

dep[N],则dep[y]=dep[x]+1,则要想求最短路径,则仅当dep[y]==dep[x]+1时才有cnt[y]+=cnt[x]

代码:

#include<bits/stdc++.h>
using namespace std;
const int MOD = 100003,N=1000005;
queue<int>Q;
vector<int >mp[N];
int dep[N], cnt[N];
bool vis[N];
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	int n,m;
	cin >> n >> m;
	while (m--)
	{
		int x, y; cin >> x >> y;
		mp[x].push_back(y);
		mp[y].push_back(x);
	}
	Q.push(1); vis[1] = 1; dep[1] = 1; cnt[1] = 1;
	while (!Q.empty())
	{
		int x = Q.front();
		Q.pop();
		for (int i = 0; i < mp[x].size(); i++)
		{
			int y = mp[x][i];
			if (!vis[y])
			{
				vis[y] = 1;
				dep[y] = dep[x] + 1;
				Q.push(y);
			}
			if (dep[y] == dep[x] + 1)
			{
				cnt[y] = (cnt[y] + cnt[x]) % MOD;
			}
		}
	}
	for (int i = 1; i <= n; i++)
	{
		cout << cnt[i] << '\n';
	}
	return 0;
}

T10 最后的舞会

思路:

注意到N<=8则直接dfs暴力求解,类似于求全排列。

代码:

#include<bits/stdc++.h>
using namespace std;
int a[20][20],res;
bool vis[20];
int n;
void dfs(int now,int ans)
{
	if (now == n)
	{
		res = max(ans, res);
		return;
	}
	else
	{
		int i, j;
		for (i = 2; i <= n+n-1; i++)
		{
			if (!vis[i])
			{
				break;
			}
		}
		for ( j = i + 1; j <= n+n; j++)
		{
			if (!vis[j])
			{
				vis[i] = 1, vis[j] = 1;
				dfs(now + 1, ans ^ a[i][j]);
				vis[i] = 0, vis[j] = 0;
			}
		}

	}
}
int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	 cin >> n;
	 if (n == 1)
	 {
		 int x;
		 cin >> x;
		 cout << x << endl;
		 return 0;
	 }
	for (int i = 1; i <= 2*n-1; i++)
	{
		for (int j = i + 1; j <= 2*n; j++)
		{
			cin >> a[i][j];
		}
	}
	vis[1] = 1;
	for (int i = 2; i <= n+n; i++)
	{
		vis[i] = 1;
		dfs(1, a[1][i]);
		vis[i] = 0;
	}
	cout << res << endl;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SET DATEFORMAT DMY 语句用于指定日期格式。 其中,D 代表日,M 代表月,Y 代表年。因此,DMY 格式表示的日期格式为日/月/年,比如 "17/12/2022"。 使用 SET DATEFORMAT DMY 语句后,SQL Server 会使用 DMY 格式来解析所有日期字符串。如果你在程序中使用了其他格式的日期字符串,它可能会导致解析错误。 例如,假设你想要插入一条记录,其中包含日期字段。如果你在插入语句中使用的日期字符串的格式与 SET DATEFORMAT DMY 指定的格式不一致,那么 SQL Server 就会报错。 因此,在使用 SET DATEFORMAT DMY 语句之前,你需要确保你的程序中使用的所有日期字符串都遵循 DMY 格式。 ### 回答2: 这段SQL语句 "SET DATEFORMAT DMY;" 的含义是将日期的格式设置为"日/月/年"。在SQL Server中,日期格式化是很重要的,因为不同的地区和国家使用不同的日期格式。 在这个特定的例子中,"SET DATEFORMAT DMY;" 语句将日期格式设置为 "日/月/年" 的格式。这意味着在执行SQL查询时,服务器会将输入和输出的日期按照这种格式进行解析和显示。 这样做的目的是确保在执行日期相关的查询时,SQL服务器正确地解析和识别日期值。例如,如果我们有一个日期字符串 "31/01/2021",在执行 "SET DATEFORMAT DMY;" 后,服务器会将其识别为 "2021年1月31日" 而不是 "2021年31日1月"。 设置正确的日期格式在确保查询结果正确性和一致性方面非常重要。如果未设置日期格式,服务器将默认使用操作系统的日期设置,这可能与我们所期望的日期格式不一致。 总之,"SET DATEFORMAT DMY;" 是一条用于设置日期格式的SQL语句,确保在执行日期相关查询时,SQL服务器能够正确解析和识别日期值。 ### 回答3: 这段SQL语句"SET DATEFORMAT DMY;"的作用是设置日期格式为日/月/年(Day/Month/Year,简写为"DMY")。在SQL服务器中,默认日期格式可能是不同的,使用该语句可以在代码中明确指定使用的日期格式。 日期格式在SQL中很重要,因为不同的日期格式会导致在查询、插入或更新数据时出现错误。特别是对于涉及日期数据的存储和操作,确保使用统一的日期格式是非常重要的。 例如,如果默认的日期格式是美国的月/日/年(MM/DD/YYYY)格式,而代码中需要使用日/月/年(DD/MM/YYYY)格式,那么在不指定日期格式的情况下执行查询可能会导致错误的结果。 通过使用"SET DATEFORMAT DMY;"语句,可以将日期格式设置为日/月/年(DD/MM/YYYY)格式,以便在代码中正确处理日期数据,避免因为日期格式不一致而引发的问题。 在执行完"SET DATEFORMAT DMY;"语句后,后续的SQL代码中使用的日期数据都会按照日/月/年的格式进行解析和操作。这将确保在查询、插入或更新日期数据时,日期将按照所需格式正确处理,并且与其他代码或应用程序的日期处理方式保持一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值