题解 | #数字匹配#

数字匹配

https://ac.nowcoder.com/acm/contest/11217/C

题目描述

dd最近比较喜欢二进制数,她认为对于任意两个正整数x,y(x<=y),当且仅当x,yx,y的二进制非前导零部分最大连续重合位数≥k时,x,y是匹配的,比如175的二进制形式为(10101111),472的二进制形式为(111011000),因此175175和472472最大连续重合部分为(1011),故这两个数的最大连续重合位数为4。 现在给定一个正整数n(n≤2000)和一个k,求对于所有x,y(且1≤x<y≤n)x,y(且1≤x<y≤n),满足条件的匹配数

输入样例

6 2

输出样例

7

算法1

(暴力枚举) O(n2)O(n^2)

题目的意思显而易见,其实这一题挺简单的就是先预处理出来1-n的二进制表示之后每长度为k的子串一存之后对于1-n中不同的两个数两两check一下就可以了 really简单但是当时看没啥人做出了我就放弃了,,,/(ㄒoㄒ)/~~

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_set>

using namespace std;

const int N=2020;
string s[N];
unordered_set<string> S[N];
bool st[N][N];

void init(int n)
{
    for(int x=0;x<=n;x++)
    {
        string str;
        for(int i=10;i>=0;i--)
        {
            if(x>>i&1) str+='1';
            else str+='0';
        }
//         cout<<str<<endl;
        int i=0;
        while(i<str.size()-1&&str[i]=='0') i++;
        str=str.substr(i);
        s[x]=str;
//         cout<<str<<endl;
    }
}

int main()
{
    int n,k;
    cin>>n>>k;
    init(n);
    int ans=0;
    for(int i=0;i<=n;i++)
    {
//         cout<<"i = "<<i<<endl;
        if(s[i].size()<k)continue;
        int len=s[i].size();
        for(int j=0;j+k-1<len;j++)
        {
            string tmp=s[i].substr(j,k);
//             cout<<"i = "<<i<<" tmp = "<<tmp<<endl;
            S[i].insert(tmp);
        }
    }
    for(int i=0;i<=n;i++)
    {
        if(s[i].size()<k)continue;
        for(int j=i+1;j<=n;j++)
        {
            for(auto t:S[i])
            {
                if(S[j].count(t)&&!st[i][j]) 
                {
//                     cout<<"i = "<<i<<" j = "<<j<<" t = "<<t<<endl;
                    ans++;
                    st[i][j]=st[j][i]=true;
                }
            }
        }
    }
    cout<<ans<<endl;
}
全部评论

相关推荐

点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务