Codeforces Round #747 (Div. 2) (21.10.9)

B. Special Numbers
题意: 给你n和k,进行幂运算,n为幂底数,将n的所有幂以及不同幂之和按顺序排列,找到第k个数。
如:n=3,k=4,序列为{1,3,4,9},表示30,31,30+31,32


分析: 比赛的时候不会做,自己想的很复杂。
以下都是废话,直接从黑体字开始看。
以n=2,k=12为例。序列幂的指数排序如下:
0 个数为1
1 01 个数为2
2 02 12 012 个数为4
3 03 13 013 23 023 123 0123 个数为8
4 04 14 014 24 024 124 0124 34 034 134 0134 234 0234 1234 01234 个数为16

序列为:
1
2 3
4 5 6 7
8 9 10 12 11 13 14 15
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

第12个数为22+23=4+8=12
找规律发现每一行的个数为2的次方,所以我先根据k找到该数在第几行(为了和幂的次方对应,假设有第0行),int m=int(log(k)/log(2)),2m为该行数的个数。然后计算k为该行的第几个数,先计算sum=20+…+2m-1,然后int t=k-sum,t为m行的第几个数,本例m=3,t=12-7=5。
然后就卡住了。。。
分析了一大堆,觉得该用二进制操作。。。


以n=2,k=12为例,我们考虑12的二进制数1100,
发现结果恰好为1 * 23+1 * 22+0 * 21+0 * 20=8+4=12,从上面的列举也能发现指数的排序为23;
以n=3,k=4为例,4的二进制数为100,结果就为1 * 32+0 * 31+0 *3 0= 9。

怎么想到的?因为不论n取什么值,指数的排列是固定的,对应的k的位置也是固定的,从上面两个表中找对应关系,发现当n取2时,序列恰好是自然数排列,那么我们找k时,无论n取什么,一定都与n=2时的k在同一个位置,自然也就对应了指数的序列。比如:k=12,n=2时指数序列为2 3,也就是二进制中1100,1代表的数。

#include<bits/stdc++.h>
using namespace std;
int mod=1e9+7;
int main()
{
    
    
    int t,n,k,ans,now;
    cin>>t;
    while(t--)
    {
    
    
        cin>>n>>k;
        ans=0,now=1;
        while(k)
        {
    
    
            if(k&1)//二进制取末尾
                ans=(ans+now)%mod;
            now=1ll*now*n%mod;//1ll表示把int转换成long long型
            k>>=1;
        }
        cout<<ans<<endl;
    }
}

C. Make Them Equal
题意:给你一个字符串s和字符c,每次操作可以选一个x(1<=x<=n),字符串不能整除x的位置上的字符替换成c,问操作几次可以使s的每一位全变成c。

分析:一开始情况没考虑全面,想的是从字符串的第2位到第n-1位找,如果有一个字符不是c,x1就等于n,然后判断第n位,如果不是c,x2就等于n-1,一共两步;如果字符串第二位到第n-1位都等于c,此时,如果第一位或第n位不是c,x1直接等于n-1即可。要么一步要么两步。
但这样写两步的时候没有考虑到2~n-1中存在一个m,且n<2*m,当2到n-1中存在一位(非m)不等于c,只需一步,x1=m。举个例子,5 b,babaa,我一开始的结果是2 5 4,实际上应该是1 3。
赛后重新修改代码

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

int main()
{
    
    
    int t,n;
    cin>>t;
    char c,s[300010];
    int cc[5];
    while(t--)
    {
    
    
        cin>>n>>c>>(s+1);
        int sum=0,p=0;
        for(int i=n-1; i>=2; i--)
        {
    
    
            if(s[i]!=c)
            {
    
    
                sum++;
                cc[p++]=n;
                break;
            }
        }
        if(sum)
        {
    
    
            if(s[n]!=c)
            {
    
    
                sum++;
                cc[p++]=n-1;
            }
        }
        else
        {
    
    
            if(s[1]!=c||s[n]!=c)
            {
    
    
                sum++;
                cc[p++]=n-1;
            }
        }
        if(sum==2)
        {
    
    
            for(int i=round((n+1)*1.0/2);i<=n-1;i++)
            {
    
    
                if(s[i]==c)
                {
    
    
                    sum=1;
                    p=1;
                    cc[0]=i;
                    break;
                }
            }
        }
        cout<<sum<<endl;
        for(int i=0; i<p; i++)
            cout<<cc[i]<<" ";
        cout<<endl;

    }
}

おすすめ

転載: blog.csdn.net/weixin_51443397/article/details/120682562