Codeforces Round #747(div2)部分题解(A~C,E1)


前言

说实话,现在的新生是一个比一个强啊。
博主刚进大学的时候啥也不会,没有参加过任何竞赛或是项目,顶多就是把C语言自学了一些。
现在都大三了,啥也没有,打了一堆铁,拿了一堆铜奖,搞得跟少林十八铜人似的,自愧不如。

再看现在的新生,各种妖魔鬼怪。真是长江后浪推前浪,前浪死在沙滩上。

在这里插入图片描述

悲伤还是要再悲伤一阵子的,我们还是先来看题解吧。


A - Consecutive Sum Riddle (思维+水题)

比赛链接:https://codeforces.com/problemset/problem/1594/A

题目大意

给定一个整数 n n n(1<= n n n<=1018),求一个区间 [ l , r ] [l,r] [l,r],满足:

1 . − 10 10 1018 ≤ l < r ≤ ≤l<r≤ l<r 10 10 1018
2 . l + ( l + 1 ) + … + ( r − 1 ) + r = n l+(l+1)+…+(r−1)+r=n l+(l+1)++(r1)+r=n

输出符合条件的 l , r l,r lr

思路

很简单的思维题。
如果n是一个奇数,我们可以把n分成 n 2 {n\over 2} 2n n 2 + 1 {n\over 2}+1 2n+1
如果n是一个偶数,那我们就可以利用对称性,取 l = 1 − n , r = n l=1-n,r=n l=1nr=n

进一步去想,其实偶数奇数都可以用对称性取 l = 1 − n , r = n l=1-n,r=n l=1nr=n
看来是我想多了 ̄□ ̄||。

AC代码

#include<bits/stdc++.h>
using namespace std;

const int maxn=2e5+100;

int a[maxn];

int main()
{
    
    
    int t;
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
    
    
        long long n;
        cin >> n;
        if(n&1) cout<<n/2<<" "<<n/2+1<<endl;
        else cout<<(n-1)*-1<<" "<<n<<endl;
    }
}

B - Special Numbers (数论+位运算)

比赛链接:https://codeforces.com/problemset/problem/1594/B

题目大意

我们定义:对于每一个数字来说都有一些对它来说比较特别的数字。

例如, 4 4 4的特别数字有: 1 1 1( 4 4 4 0 0 0),4( 4 4 4 1 1 1),5( 4 4 4 1 1 1+ 4 4 4 0 0 0),16( 4 4 4 2 2 2),17( 4 4 4 2 2 2+ 4 4 4 0 0 0),20( 4 4 4 2 2 2+ 4 4 4 1 1 1), . . . ... ...

现在给出整数 n n n,求 n n n的第 k k k个特别数字。
由于答案可能很大,答案需要对109+7取模。

思路

一个数论,但没有那么难,也是见到过很多次了。
我们分析一下例子中的数字:
在这里插入图片描述我们可以发现:n的第k个特殊数字是根据k的二进制来求的。

根据得到的规律就可以很轻松的解决问题了。

AC代码

#include<bits/stdc++.h>

using namespace std;

const long long mod=1e9+7;
const int maxn=2e5+100;

//快速幂,没用上
long long quickpower(long long base,long long power)
{
    
    
    long long result=1;
    while(power){
    
    
        if(power&1) result=(result*base)%mod;
        power>>=1;
        base=(base*base)%mod;
    }
    return result;
}

int main()
{
    
    
    int t;
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
    
    
        long long n,k;
        cin>>n>>k;
        vector<int> arr;
        while(k){
    
    
            arr.push_back(k%2);
            k/=2;
        }
        long long ans=0;
        long long m=1;
        for(int i=0;i<arr.size();i++){
    
    
            if(arr[i]) ans=(ans+m)%mod;
            m=(m*n)%mod;
        }
        cout<<ans<<endl;
    }
}

C - Make Them Equal (思维)

比赛链接:https://codeforces.com/problemset/problem/1594/C

题目大意

给一个字符串长度为 n n n的字符串 s s s与一个字符 c c c
问你最少需要多少次操作可以把字符串中所有的字符都变成字符 c c c

操作方法:
选择一个数字 x ( 1 < = x < = n ) x(1<=x<=n) x(1<=x<=n),把所有无法整除 x x x的下标i位置的字符 s [ i ] s[i] s[i]变成 c c c

输出操作次数与每次操作的 x x x的值。

思路

1.首先考虑特殊情况:字符串s中所有的字符都是c,就不需要操作;

2.其次,先考虑1次操作能不能全部解决:

第一种可行方案:我们要找一个不能被其他数整除的下标,并且这个下标处的字符已经是c了。
这种下标存在于 [ n 2 + 1 , n ] [{n\over 2}+1,n] [2n+1n]

int pos=-1;
for(int i=n/2+1; i<=n; i++)
{
    
    
	if(s[i-1]==a)
	{
    
    
		pos=i;
		break;
	}
}
if(pos!=-1) cout<<"1\n"<<pos<<endl;

第二种可行方案:模拟x所有可能的值,暴力跑出结果。

for(int i=2; i<=n; i++)
{
    
    
    flag=true;
    for(int j=i; j<=n; j+=i)
    {
    
    
        if(s[j-1]!=a)
        {
    
    
            flag=false;
            break;
        }
    }
    if(flag)
    {
    
    
        pos=i;
        break;
    }
}
if(pos!=-1) cout<<"1\n"<<pos<<endl;

3.最后,如果还是不存在那么我们就直接选择 x = n x=n x=n x = n − 1 x=n-1 x=n1

由于 1 − n 1-n 1n中只有 n n n可以整除 n n n,除了 n n n位置上的字符其他的字符都会变成 c c c;紧接着又由于 1 − n 1-n 1n中只有 n − 1 n-1 n1可以整除 n − 1 n-1 n1,此时再把 n n n位置上的字符改成 c c c

AC代码

#include<bits/stdc++.h>

using namespace std;

const long long mod=1e9+7;
const int maxn=2e5+100;

int main()
{
    
    
    int t;
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
    
    
        int n;
        char a;
        string s;
        cin>>n>>a;
        cin>>s;
        int flag=true;
        for(int i=0; i<n; i++)
            if(s[i]!=a)
            {
    
    
                flag=false;
                break;
            }
        if(flag)
            cout<<"0"<<endl;
        else
        {
    
    
            int pos=-1;
            for(int i=n/2+1; i<=n; i++)
            {
    
    
                if(s[i-1]==a)
                {
    
    
                    pos=i;
                    break;
                }
            }
            if(pos!=-1) cout<<"1\n"<<pos<<endl;
            else
            {
    
    
                for(int i=2; i<=n; i++)
                {
    
    
                    flag=true;
                    for(int j=i; j<=n; j+=i)
                    {
    
    
                        if(s[j-1]!=a)
                        {
    
    
                            flag=false;
                            break;
                        }
                    }
                    if(flag)
                    {
    
    
                        pos=i;
                        break;
                    }
                }
                if(pos!=-1) cout<<"1\n"<<pos<<endl;
                else
                {
    
    
                    cout<<"2\n"<<n<<" "<<n-1<<endl;
                    
                }
            }
        }

    }
}

E1 - Rubik’s Cube Coloring (easy version) (思维+取模运算)

比赛链接:https://codeforces.com/problemset/problem/1594/E1

题目大意

你现在有一颗高度为k的满二叉树,树上有 2 k − 1 2^k-1 2k1个结点。
现在你要为这颗树上的结点涂色,可以选择6种不同的颜色为树涂色,并且需要遵循一下规则:

  1. 白色结点不能和白色/黄色结点相邻
  2. 黄色结点不能和白色/黄色结点相邻
  3. 绿色结点不能和绿色/蓝色结点相邻
  4. 蓝色结点不能和绿色/蓝色结点相邻
  5. 红色结点不能和红色/橘色结点相邻
  6. 橘色结点不能和红色/橘色结点相邻

问,一共有多少种涂色的方式?

思路

一个简单的思维题。

简单来说就是我们给一个结点涂上任意一种颜色之后,它的两个相邻结点就会少两种颜色。
相邻:结点A与结点B之间有一条边。

那这样的话,一开始整棵树都没有颜色,所以根节点可以6选1。剩下的结点都只能选4种。
所以答案就是 6 ∗ 4 6*4 64 2 k − 2 2^k-2 2k2

中间涉及到取模,对于 2 2 2 k k k 如果我们再使用快速幂去算会导致最后的答案缺失很多。
(测试点 k = = 60 k==60 k==60,可以自己比较一下两者的值)

这里可以使用位运算:

1<<n  <==> 2^n

然后转成long long,保证了精度与答案的准确性。

AC代码

#include<bits/stdc++.h>
using namespace std;

const long long mod=1e9+7;

long long quickpower(long long base,long long power)
{
    
    
    long long result=1;
    while(power){
    
    
        if(power&1) result=(result*base)%mod;
        power>>=1;
        base=(base*base)%mod;
    }
    return result;
}

int main()
{
    
    
    long long n;
    cin>>n;
    long long power=(1LL<<n)-2;
    //cout<<power<<endl;
    cout<<(6*quickpower(4,power))%mod<<endl;
}

感谢阅读,希望能对你产生一点用处。
(人人视频上权游七八季下架了,呜呜呜)

在这里插入图片描述

"Valar Morghulis."
"Valar Dohaeris."

吾日三省吾身:日更否?刷题否?快乐否?
更新了,但不是日更;已刷;happy!
吾心满意足。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45750296/article/details/120722645