//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

2023.7.8洛谷月赛

洛谷2023.7.8月赛

T1

观察发现合法的数转成二进制只有两种情况。

一种是一个一,这种直接加一输出就好。

一种是两个一,我们手模一下 \(12\) 这种就能发现,直接加上最小的一位一的值就可以得到下一位数,当然有可能两个一是相邻的,这种情况实际上是不会影响答案的。

有个求 popcount 的 STL,WA 了好久才知道只能处理 \(32\) 位。

#include <bits/stdc++.h>

#define int long long
#define N 1000100

using namespace std;

int T, n;

inline int popcount(int x)
{
    int ans = 0;
    while(x) ans ++, x -= (x & (-x));
    return ans;
}

signed main()
{
	cin >> T;
	while(T --)
	{
		cin >> n;
		int cnt = popcount(n), k = 0;
		if(cnt >= 3) {cout << "No,Commander" << endl; continue;}
		if(cnt <= 1) {cout << n + 1 << endl; continue;}
		if(cnt == 2)
		{
			while((n & (1ll << k)) == 0) k ++;
			cout << (n + (1ll << k)) << endl;
		}
	}
	return 0;
}

T2

就是让你构造一堆操作,解决类似汉诺塔的问题。

我们不难发现可以直接暴力来求,操作数要小于 \(1e6\),但 \(n\le 1300\),所以我们可以尽情发挥。

我们需要开两个栈来模拟题目,首先我们初始都在 A 上,我们通过不断的弹栈入栈把当前不需要的圆盘在 AB 之间移动,当我们找到需要的盘子的时候,直接放进 C 即可,因为最坏就是一个需要挪一堆,最坏其实是 \(1300^{2}\),但想到我们是在 AB 上,我们在从一根挪到另一根的时候,我们可以直接不再挪回来,直接留在那里,然后我们再从这些柱子里找,均摊一下大约最坏 \(\frac{1300^{2}}{2}\)(?

code:

#include <bits/stdc++.h>

#define int long long
#define N 1000100

using namespace std;

int n, cnt, a[N], s[N];//1是A盘上,2是B盘上,3是C盘上 
stack<int> q1, q2;
char s1[N], s2[N];

signed main()
{
    cin >> n;
    for(int i = 1; i <= n; i ++)
        cin >> s[i], a[s[i]] = 1;
    for(int i = n; i >= 1; i --)
        q1.push(s[i]);
    for(int i = n; i >= 1; i --)
	{
        if(a[i] == 1)
		{
            while(!q1.empty() && q1.top() != i)
			{
                a[q1.top()] = 2;
                q2.push(q1.top());
                q1.pop();
                s1[++ cnt] = 'A';
				s2[cnt] = 'B';
            }
            a[q1.top()] = 3;
            q1.pop();
            s1[++ cnt] = 'A';
			s2[cnt] = 'C';
        }
        else if(a[i] == 2)
		{
            while(!q2.empty() && q2.top() != i)
			{
                a[q2.top()] = 1;
                q1.push(q2.top());
                q2.pop();
                s1[++ cnt] = 'B';
				s2[cnt] = 'A';
            }
            a[q2.top()] = 3;
            q2.pop();
            s1[++ cnt] = 'B';
			s2[cnt] = 'C';
        }
    }
    cout << cnt << endl;
    for (int i = 1; i <= cnt; i ++)
        cout << s1[i] << " " << s2[i] << endl;
    return 0;
}

T3

考试打了个暴力,思路是直接暴力描述第二个串,然后求所有的个数的 \(\gcd\) 然后一除,就得到了压缩后的第二个串,然后再每次累加串的总长直接匹配,最后判断是不是倍数关系。

特殊性质一比较好打,就是第二个串都是一个字符,直接用前缀和啥的乱搞就行。

特殊性质二就是分成了两段,挂了。。

暴力:

#include <bits/stdc++.h>

#define int long long
#define N 5000100

using namespace std;

int n, m, s1[N], s2[N], a[N], b[N], cnt;
int A[N], B[N], cc, ans, ff1 = 1, ff2 = 1;
int cnt1, cnt2;

inline void js(int cntl, int cntr, int &ans)
{
    int k = 0;
    while(k * cnt1 <= cntl && k * cnt2 <= cntr) k ++;
    ans += (k - 1);
    return ;
}

inline void solve1()
{
    int len = 0;
    for(int i = 1; i <= n; i ++)
    	A[i] = A[i - 1] + i;
    for(int i = 1; i <= n; i ++)
	{
        if(s1[i] != s1[i - 1])
		{
            if(s1[i - 1] == s2[1]) ans += A[len];
            len = 1;
        }
        else len ++;
    }
    if (len && s1[n] == s2[1]) ans += A[len];
    cout << ans << endl;
    exit(0);
}

inline void solve2()
{
    int last = -1, lastcnt = 0, cnt = 1, k = -1;
    for(int i = 1; i <= m; i ++)
        if(s2[i] != s2[i + 1] && i != m) k = i;
    cnt1 = k, cnt2 = m - k;
    int xx = __gcd(cnt1, cnt2);
    cnt1 /= xx;
	cnt2 /= xx;
    if(k == -1)exit(0);
    for(int i = 2; i <= n; i ++)
	{
        if(s1[i] != s2[i - 1])
		{
            if(last == s2[k] && s1[i - 1] == s2[k + 1])
                js(lastcnt, cnt, ans);
            lastcnt = cnt;
            last = s1[i - 1];
            cnt = 1;
        }
        else cnt ++;
    }
    if(last == s2[k] && s1[n] == s2[k + 1])
        js(lastcnt, cnt, ans);
    cout << ans << endl;
    exit(0);
}

signed main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> s1[i];
	for(int i = 1; i <= m; i ++) cin >> s2[i];
	for(int i = 1; i <= m; i ++)
	{
		if(i != 1 && s2[i] != s2[i - 1])
		{
			ff1 = 0;
			if(ff2 == 1) ff2 = 2;
			else ff2 = 0;
		}
	}
	if(ff1) solve1();
//	if(ff2 == 2) solve2();
	for(int i = 1; i <= m; i ++)
	{
		if(s2[i] != s2[i - 1]) a[++ cnt] = s2[i];
		b[cnt] ++;
	}
	int xx = b[1], len = 0;
	for(int i = 2; i <= cnt; i ++) xx = __gcd(xx, b[i]);
	for(int i = 1; i <= cnt; i ++) b[i] /= xx, len += b[i];
	int nn = len, cao = 1;
	while(nn <= n)
	{
		for(int i = 1; i + nn - 1 <= n; i ++)
		{
			cc = 0;
			for(int o = 1; o <= cnt; o ++) A[o] = B[o] = 0;
			int j = i + nn - 1, ff = 1;
			int cccc = s1[i - 1];
			s1[i - 1] = 1e9;
			for(int o = i; o <= j; o ++)
			{
				if(s1[o] != s1[o - 1]) A[++ cc] = s1[o];
				B[cc] ++;
			}
			if(cc != cnt) {s1[i - 1] = cccc; continue;}
			for(int o = 1; o <= cc; o ++)
			{
				if(A[o] != a[o]) {ff = 0; break;}
				if(B[o] / cao != b[o]) {ff = 0; break;}
			}
//			cout << B[1] << "  i :" << i << " DDDD: " << nn << " ff :" << ff << "  cao :" << cao << endl;
			if(ff) ans ++;
		}
		nn += len;
		cao ++;
	}
//	for(int i = 1; i <= n; i ++) cout << s1[i] << " "; cout << endl;
	cout << ans << endl;
	return 0;
}
posted @ 2023-07-08 22:01  北烛青澜  阅读(7)  评论(0)    收藏  举报