week15

1.帅到没朋友

 思路:

用一个很大的数组记录每个编号的人有没有朋友,如果朋友圈人数>1,那就把朋友圈历代每个人标记为有朋友,之后输出,输出之后把没朋友的人呢标记为有朋友,防止多次输出,记得格式控制.

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int x[N];
int main() {
	int n;
	cin >> n;
	for (int k9 = 0; k9 < n; k9++) {
		int y9;
		cin >> y9;
		if (y9 > 1) {
		for (int e = 0; e < y9; e++) {
			int y8;
			cin >> y8;
			x[y8] = 1;
		}
		/*do {
			int y8;
			cin >> y8;
			x[y8] = 1;
		} while (getchar()!='\n');*/
		}
		else {
			cin >> y9;
		}
	}
	int y7;
	cin >> y7;
	int panduan = 1;
	int pank = 0;
	for (int e = 0; e < y7; e++) {
		int y6;
		cin >> y6;
		if (x[y6] == 0) {
			panduan=0;
			x[y6] = 1;
			if (pank == 0) {
				pank++;
			}
			else {
				cout <<" ";
			}
			printf("%05d", y6);
		}
	}
	if (panduan == 1) {
		cout <<"No one is handsome";
	}
}

 2.快快长大

这是帮助我理解石子合并的一张图

把石子合并的模板改一改套上来,至于sum的统计可以用一个二维数组事先计算好 

#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[305][305];
int mul[305][305];
int shujv[305];
const int mod = 1000003;
signed main() {
	int n;
	cin >> n;
	for (int e = 1; e <= n; e++) {
		cin >> shujv[e];
	}
	for (int i = 1; i <= n; i++) {
		mul[i][i] = shujv[i];
		for (int j = i + 1; j <= n; j++) {
			mul[i][j] = mul[i][j - 1] * shujv[j] % mod;
		}
	}
	for (int e = 1; e <= n; e++) {
		dp[e][e] = 0;
	}
	for (int len = 1; len <= n; len++) {
		for (int i = 1; i + len - 1<=n; i++) {
			int j = i + len - 1;
			for (int k = i; k < j; k++) {
				dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + (mul[i][k]-mul[k+1][j])*(mul[i][k] - mul[k + 1][j]));
			}
		}
    }
	/*for (int e = 1; e <= n; e++) {
		for (int e2 = 1; e2 <= n; e2++) {
			cout << mul[e][e2] << " ";
		}cout << endl;
	}*/
	cout << dp[1][n];
}

 3.饿饿饭饭2 

思路:

求出给出数的最大公约数,然后用dfs将每个数除2除3看能否成为公约数.

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 3e5;
int shuzhu[N];
int panduan = 0;
int gcd(int a, int b) {
	if (b)while ((a %= b) && (b %= a));
	return a + b;
}
void dfs(int x, int y) {
	if (x == y) {
		panduan = 1;
		return ;
	}
	if (x % 2 != 0 && x % 3 != 0) {
		return ;
	}
	if (x % 2 == 0) {
		dfs(x / 2, y);
	}
	if (x % 3 == 0) {
		dfs(x / 3, y);
	}
	return ;
}
signed main() {
	int x9;
	cin >> x9;
	while (x9--) {
		int n, a; 
		cin >> n;
		for (int e = 1; e <= n; e++) {
			cin >> shuzhu[e];
		}
		int gys=shuzhu[1];
		for (int e = 1; e < n; e++) {
			gys = gcd(gys, shuzhu[e + 1]);
		}
		panduan = 0;
		int panduan2 = 1;
		//cout << "gys" << gys << endl;
		for (int e = 1; e <= n; e++) {
			dfs(shuzhu[e], gys);
			if (panduan == 1) {
				panduan = 0;
			}
			else {
				//cout << shuzhu[e] << endl;
				panduan2 = 0;
				break;
			}
		}
		if (panduan2 == 1) {
			cout << "YES" << endl;
		}
		else {
			cout << "NO" << endl;
		}
	
	}
	
}

4.子串分值和 

思路:

这道题表面就跟题目上个说的一样,把三个for循环把题目上的公式表达出来就好了,但是实际会超时,怎么办呢,首先我优化了一下内循环,当i不变,j不断扩大的时候,i-j从每次都要从a[i]循环判断到a[j]变成一个变量leiji记录累计数值,每次只判断a[j],如果jilu[a[j]]==0,也就是a[j]这个字符是新的的时候,jilu[a[j]]++,然后lieji++;for循环j从i到len-1的过程中he不断+=leiji,最后就是答案,但是,还是超时.

没法子,接着优化外循环,设置一个变量次次记录cicijilu来记录外层循环每次的结果,这时只需要完全遍历一次字符串就可以了,i从0开始遍历到len,然后得到第一个cicijilu的值,之后i从0到len的过程中,只要判断当前a[i]在记录数组jilu中的值-1是否等于0,如果等于零,那cicijilu的值cicijilu =cicijilu-(len-i);也就是模拟之前的循环每次加的数值-1,如果不等于0,那就循环每次cicijilu-1,直到找到第一个与该字符相同的字符.

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
int jilu[200];
signed main() {
	string a;
	cin >> a;
	int len = a.size();
	int he = 0;
	int cicijilu = 0;
	int leiji = 0;
	for (int j = 0; j < len; j++) {
		if (jilu[a[j]] == 0) {
			leiji++;
		}
		jilu[a[j]]++;
		cicijilu += leiji;
	}
	he += cicijilu;
	//cout << cicijilu << endl;
	for (int i = 0; i < len; i++) {
	//	cout <<"a[i]=" << a[i]<< endl;
	//	cout <<"jilu[a[i]] - 1 =" << jilu[a[i]] - 1 << endl;
		if (jilu[a[i]] - 1 == 0) {
			jilu[a[i]]--;
			cicijilu =cicijilu-(len-i);
			he = he + cicijilu;
			//cout << "cicijilu2" << cicijilu << endl;
		}
		else {
			jilu[a[i]]--;
			cicijilu--;
			for (int e = i + 1; e < len; e++) {
				if (a[i] == a[e]) {
					break;
				}
				else {
					cicijilu--;
				}
			}
		//	cout << "cicijilu" << cicijilu << endl;
			he += cicijilu;
		}
		//cout << endl;
	}
	cout << he;
}

5.蒟蒻

 思路:

单纯的if else然后考查容器的使用

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
vector<pair<int, int>>hhh;
void p(int x) {
	if (x == 2) {
		int zuo = 0;
		int minx = 0x7fffffff;
		for (int e = 0; e < hhh.size(); e++) {
			if (hhh[e].first <= minx) {
				zuo = e;
				minx = hhh[e].first;
			}
		}
		hhh.erase(hhh.begin() + zuo);
	}
	else {
		int zuo = 0;
		int minx = 0x7fffffff;
		for (int e = 0; e < hhh.size(); e++) {
			if (hhh[e].second <= minx) {
				zuo = e;
				minx = hhh[e].second;
			}
		}
		hhh.erase(hhh.begin() + zuo);
	}
}
int main() {
	int a9;
	cin >> a9;
	while (a9--) {
		int a, b, c;
		cin >> a;
		if (a == 1) {
			cin >> b >> c;
			int panduan = 1;
			for (int e = 0; e < hhh.size(); e++) {
				if (hhh[e].first == b || hhh[e].second == c) {
					panduan = 0;
					break;
				}
			}
			if (panduan == 1) {
				hhh.push_back(make_pair(b, c));
			}
		}
		else {
			p(a);
		}
	}
	int he = 0;
	for (int e = 0; e < hhh.size(); e++) {
		he += hhh[e].first;
	}
	cout << he;
}

6.锦标赛 

 思路:

开始想复杂了,这个题的意思就是只要你能力高,你就绝对能赢,如果对手能力比你高的程度在一定限度内,你还是可能能赢,既然他问可能有对少人能赢,那就是尽可能让每个人都能赢,就是通过最高能力值低小于k能力的人战胜最高能力值的人来降低能力值上限,不断操作来让我们的目标人物有可能获胜,开始的时候想的太复杂,一个人一个人的处理,把比这个人能力高出k的人都赛进一个新容器里,然后挨个判断能不能降到目标人物能力差k以内,结果超时了.

然后重新整理一下思路,我们可以先用vector录入数据,然后sort排序,从大到小,之后for遍历,只要

ren[e]-ren[e-1]<=k,就说明可以通过这个人把能力值上限降下来,人数++,如果不行,那这个链就此断裂,以后的也肯定不行了,break;

因为确认了第一个人呢肯定能赢,所以最开始设置变量he的时候记得把he的值设置为1

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
vector<int>ren;
bool cmp(int a,int b) {
	return a > b;
}
signed main() {
	int a,b;
	scanf("%lld%lld", &a, &b);
	while (a--) {
		int c;
		scanf("%lld", &c);
		ren.push_back(c);
	}
	sort(ren.begin(), ren.end(),cmp);
	int he = 1;
	for (int e = 0; e < ren.size()-1; e++) {
		if (ren[e] - ren[e + 1] <= b) {
			he++;
		}
		else {
			break;
		}
	}
	printf("%lld", he);
}

7.可重排列 

 

思路:

学会了新的bfs表示方法,太强了,本来按照我的思路先拿普通的bfs排序然后记录每个例子有没有被输出过,结果就是超时,学习了大佬的bfs排序方法,ac了 

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
vector<int>shuzu;
vector<int>shuzupd;
vector<int>ans;
int n;
int n2=0;
int f[15];
void dfs() {
	if (ans.size()==n2) {
		for (int e = 0; e <ans.size(); e++) {
			printf("%d ", ans[e]);
		}printf("\n");
		return;
	}
	for (int e = 1; e <=n; e++) {
		if (f[e] != 0) {
			f[e]--;
			ans.push_back(e);
			dfs();
			ans.resize(ans.size() - 1);
			f[e]++;
		}
	}
}
int main() {
	scanf("%d", &n);
	for (int e = 1; e <= n; e++) {
		int b;
		scanf("%d", &b);
		n2 += b;
		f[e] = b;
	}
	dfs();
}

8.进制转换 

 思路:

先把每个数字对应的值录入一个数组,然后接收数据,把所有的数都化成十进制加起来,最后再转化成目标进制的数

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char v[70];
int main()
{
    int n, m;
    vector<ll>mymap(100);
    ll ans = 36;
    for (char c = 'a'; c <= 'z'; c++)
    {
        v[ans] = c;
        mymap[c - 65] = ans++;
    }
    for (char c = '0'; c <= '9'; c++)
        v[c - '0'] = c;
    ans = 10;
    for (char c = 'A'; c <= 'Z'; c++)
    {
        v[ans] = c;
        mymap[c - 65] = ans++;
    }
    ll sum = 0;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        string s;
        int t;
        cin >> t >> s;
        ans = 1;
        int len = s.size();
        for (int j = len - 1; j >= 0; j--)
        {
            if (s[j] >= '0' && s[j] <= '9')sum += (s[j] - '0') * ans;
            else sum += mymap[s[j] - 65] * ans;
            ans *= t;
        }
    }
    string str;
    while (sum)
    {
        ll num = sum % m;
        str += v[num];
        sum /= m;
    }
    reverse(str.begin(), str.end());
    cout << str << endl;
    return 0;
}

9.循环子串 

 

 思路:

就是说从字符串a里找子字符串,然后看子字符串能否在循环a中找到,如果循环的话会比较麻烦,所以我们可以直接a+a,只要能在a+a中找到,就相当于在循环字符串找到.

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        string s;
        cin >> n >> s;
        bool flag = true;
        string str = s + s;
        for (int len = 2; len <= n; len++)
        {
            for (int i = 0; i + len <= n; i++)
            {
                string res = s.substr(i, len);
                reverse(res.begin(), res.end());
                if (str.find(res) == str.npos)
                {
                    cout << "NO" << endl;
                    flag = false;
                    break;
                }
            }
            if (!flag)break;
        }
        if (flag)cout << "YES" << endl;
    }
    return 0;
}

10.饿饿饭饭之暑假大狂欢

思路:

只要自己的数字不完全包含别人的数字,就可以胜利

#include<iostream>
using namespace std;
int mymap[101][101];
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t, n;
    cin >> t;
    for (int i = 0; i < t; i++)
    {
        cin >> n;
        for (int j = 0; j < n; j++)
        {
            int num;
            cin >> num;
            mymap[i][num] = 1;
        }
    }
    for (int i = 0; i < t; i++)
    {
        bool flag = true;
        for (int j = 0; j < t; j++)
        {
            if (i == j)continue;
            bool st = false;
            for (int k = 0; k <= 100; k++)
            {
                if (mymap[i][k] < mymap[j][k])
                {
                    st = true;
                    break;
                }
            }
            if (!st)
            {
                flag = false;
                break;
            }
        }
        if (!flag)
        {
            cout << "NO" << endl;
        }
        else cout << "YES" << endl;

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唏嘘南溪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值