暑假训练第一周第六天

题意:
A(CodeForces - 1249 C1&C2):找一个最小的大于n的数,要求是3的幂次和且每个次数最多出现一次。
B(CodeForces - 1249A )一组数,如果有两数之差为一,把他们放在两个不同的组里。
C(CodeForces - 1249 D1&D2):给多组线段,每一个点的覆盖次数不超过K,每次可去除一个线段,问最少去多少线段以及线段的位置。
D(CodeForces - 1249 B1&B2):数组a[n],每过一天书会从i转到a[i],问多少天回到最开始的人手里。
题解:
A&E CodeForces - 1249 C1&C2 Good Numbers
思路:1、通过判断n%3=2,2=3的0次方+3的0次方所以只要n%3=2就不符合要求
2、利用三进制所以,对于位为0、1的情况不处理,只对位为2的处理,处理成“3”,也就是本位记0,然后进位给下一位。所以每次获取的新本位是由原本位和进位决定的。这样处理完之后,得到的结果是可能偏大的,因为可能高位就已经保证了整个数是大于等于n的,所以多余的低位会让结果更大,所以要比较每一个的新位与原位,如果它们相等,那么这一位就是必须的,最后转换回十进制。
代码:
1、

#include<bits/stdc++.h>
int q,sum,m,n;
using namespace std;
int main()
{
	int q;
	cin>>q;
	while (q--)
	{
		cin>>m;
		n = m;
		sum = 0;
        while (1)
		{
		    bool f = true;
			while (n > 0)
			{
				if (n % 3 == 2)
				{
					f = false;
					break;
				}
				n = n / 3;
			}
			if (f == true)
			{
				cout<<m+sum<<endl;
				break;
			}
			else
			{
				++sum;
				n = m + sum;
			}

		}
	}
}

2、

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int M = 60;
int bit[M], abit[M], cnt;
long long pow3[M];
int main() {
	pow3[0] = 1;
	for (int i = 1; i < M; i++) pow3[i] = pow3[i - 1] * 3;
	ll t, n, m, carry, temp, ans;
	cin >> t;
	while (t--) {
		cin >> n;
		m = n;
		carry = 0;
		for (cnt = 0; m; cnt++) {
			bit[cnt] = m % 3;
			temp = bit[cnt] + carry;
			if (temp == 0) abit[cnt] = 0;
			else if (temp == 1) abit[cnt] = 1, carry = 0;
			else if (temp >= 2) abit[cnt] = 0, carry = 1;
			m /= 3;
		}
		if (carry) {
			bit[cnt] = 0;
			abit[cnt] = 1;
			cnt++;
		}
		cnt--;
		ans = 0;
		while (cnt >= 0) {
			if (abit[cnt] > bit[cnt]) {//1,0
				ans += pow3[cnt];
				break;
			}
			else if (abit[cnt] == bit[cnt]) ans += abit[cnt] * pow3[cnt];
			cnt--;
		}
		cout << ans << endl;
	}
	return 0;
}

G CodeForces - 1249 B2 Books Exchange (hard version)(队列)
思路:用队列来储存变换的
代码:

#include<bits/stdc++.h>
using namespace std;
int t,n;
int a[220000],b[220000];
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        queue<int>q;
        for(int i=1;i<=n;i++)
        {
            if(b[i])
                continue;
            int m=i;
            do
            {
                q.push(m);
                m=a[m];
            }while(m!=i);
            int ans=q.size();
            while(!q.empty())
            {
                b[q.front()]=ans;
                q.pop();
            }
        }
        for(int i=1;i<n;i++)
       cout<<b[i]<<' ' ;
      cout<<b[n]<<endl;
    }
    return 0;
}

感想:感觉状态多多少少回来一点了。A想打表来着,WA之后发现要打两次,想想还是算了,就换了种思路。D题就毫无思路,B2的话是真的没往队列上靠,知识点的应用能力还是差太多,明天把学过的都列出来,弄个思维导图。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值