Codeforces Round #451 (Div. 2)

https://codeforces.com/contest/898

A:
题意;
给出一个数字 ,四舍五入一下。

题解 :
四舍五入

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int main()
{
    int n;
    while(cin>>n)
    {
        if(n%10<=5) cout<<n-n%10<<endl;
        else cout<< n-n%10+10 <<endl;
    }
}

B
题意:
给出三个数字 N,A,B。
找到两个数字 x,y
xa+yb==n

题解;
使得n%a 的余数 依次增加a ,直到可以整除b为止

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int main()
{
    int n,a,b;
    while(cin>>n>>a>>b)
    {
        int mod=n%a;
        int x=n/a,y=0;
        while(mod&&x)
        {
            mod=(mod+a)%b;
            x--;
        }
       if(mod==0) cout<<"YES"<<endl<<x<<' '<<(n-x*a)/b<<endl;
       else cout<<"NO"<<endl;
    }
}



C

前导0好烦啊。还要保留前导0 ,有毒。

#include<bits/stdc++.h>
using namespace std;
const long long maxn = 1e5 + 5;
map<string, long long > tag;
map<string, vector<string > > phone;
long long huan ( string &s )
{
    long long ans = 0;
    for ( int i = 0; s[i]; i++ )
        ans = ans * 10 + s[i] - '0';
    return ans;
}
bool cmp ( string &a, string &b )//引用可以降低空间损耗和时间。
{
    long long x = huan ( a );
    long long y = huan ( b );
    if ( x != y )
        return x > y;
    else
        return a.size() > b.size();
}
int main()
{
    long long n;
    while ( cin >> n )
    {
        string str, x;
        long long m;
        for ( long long i = 0; i < n; i++ )
        {
            cin >> str >> m;
            for ( long long i = 0; i < m; i++ )
            {
                cin >> x;
                phone[str].push_back ( x );
            }
        }

        cout << phone.size() << endl;
        for ( auto i = phone.begin(); i != phone.end(); i++ )
        {
            vector<string > &temp = i->second, pl;
            sort ( temp.begin(), temp.end(), cmp );
            cout << i->first << ' ';
            tag.clear();
            for ( long long j = 0; j < temp.size(); j++ )
            {
                string num = temp[j];
                if ( !tag[num] )
                {
                    string e;
                    for ( long long i = num.size() - 1; i >= 0; i-- )
                    {
                        e = num[i] + e;
                        tag[e] = 1;
                    }
                    pl.push_back ( num );
                }
            }
            cout << pl.size() << ' ';
            for ( long long j = 0; j < pl.size(); j++ )
                cout << pl[j] << ' ';
            cout << endl;
        }
    }
    return 0;
}






程序员就要反复推敲代码已追求代码的极致。

D

一直在调边界- -

#include <bits/stdc++.h>

const int maxn = 2e5 + 5;


using std::cin;

int a[maxn];

std::queue<int > q;
int main()
{
    int n, m, k;
    while ( cin >> n >> m >> k )
    {
        for ( int i = 1; i <= n; i++ )
        {
            cin >> a[i];
        }
        std::sort(a+1,a+n+1);

        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(q.size()<k-1)
            {
                q.push(a[i]);
            }
            else if(q.size()&&a[i]-q.front()>m-1)
            {
                while(q.size()&&a[i]-q.front()>m-1 ) q.pop();
                q.push(a[i]);
            }
            else
            {


                ans++;
            }
           //std::cout<<"asd   "<<a[i]<<std::endl;
        }
        std::cout<<ans<< std::endl;
    }
}

https://codeforces.com/contest/898/problem/E

题意:
每次可以让一个数字增加1,可以让一个数字减少1(当这个数字大于0的时候)

然后 ,要让一半的数字是平方数,另一半不是平方数,求最少的操作次数;

题解:
二分查找最近的平方数,按照差值排序
因为0想变成非平方数需要操作两次。所以 在寻找平方数的时候优先使用0;
最后求和。

#include <bits/stdc++.h>

const long long maxn=2e5+5;
using std::cin;
using std::cout;
using std::endl;

struct node
{
    long long x,y,z;
}a[maxn];
bool cmp(node a,node b)
{

   if(a.y!=b.y) return a.y<b.y;
   else return a.z>b.z;
}
bool cmp1(node a,node b)
{
    return a.z<b.z;
}
long long powe[maxn];
int main()
{
    long long n;
    for(long long i=0;i<=35000;i++) powe[i]=i*i;
    while(cin>>n)
    {
        long long x,y;
        for(long long i=0 ;i< n ; i++ )
        {
            cin >> a[i].x;
            long long v=std::lower_bound(powe,powe+34000,a[i].x)-powe;

            x=v,y=std::max((long long)0,v-1);
            a[i].y=std::min( abs(powe[x]-a[i].x) ,abs(powe[y]-a[i].x) );
            if(a[i].x==0) a[i].z=2;
            else if(a[i].y==0) a[i].z=1;
            else a[i].z=0;
        }

        std::sort(a,a+n,cmp);

        long long ans=0;
        for(long long i=0;i<n/2;i++)
        {
            ans+=a[i].y;
          //  cout<<ans<<' '<<a[i].x<<' '<<a[i].y<<' '<<a[i].z<<endl;
        }
        std::sort(a+n/2,a+n,cmp1);
      //  cout<<"xxxxxxxxxxxxx "<<endl;
        for(long long i=n/2;i<n;i++)
        {
            ans+=a[i].z;
          //  cout<<ans<<' '<<a[i].x<<' '<<a[i].y<<' '<<a[i].z<<endl;
        }

        cout<<ans<<endl;
    }
}

https://codeforces.com/contest/898/problem/F
题意:
给一个字符串s,
把字符串分成a+b=c的形式;

题解 :
首先可以知道,只需要枚举位置 去判断a+b==c 就可以了
其实大数可做,但是大数的每次判断是o(n) 加上枚举位置
复杂度为n^2
所以 将大数需要判断的地方改成字符串哈希
为了准确,用两个哈希表去判断。
知识点:字符串哈希。加法运算;

注意判断间隔点,a,b,c 都至少包含一位数,并且不存在前导0

#include <bits/stdc++.h>
using namespace std;
const long long base = 10;
const long long mod1 = 1e8 + 7, mod2 = 1e7 + 7;
const long long maxn = 1e6 + 5;
long long hash1[maxn], hash2[maxn], mu1[maxn], mu2[maxn];
string s;
void show ( long long x, long long y, long long z )
{
    for ( int i = 0; i < x; i++ )
    {
        cout << s[i];
    }
    cout << "+";
    for ( int i = x; i < y; i++ )
        cout << s[i];
    cout << "=";
    for ( int i = y; s[i]; i++ )
        cout << s[i];
    cout << endl;
}
void check ( long long x, long long y, long long z )
{
    long long a = ( hash1[x] + hash1[y] - hash1[x] * mu1[y - x] % mod1 + mod1 ) % mod1;
    long long b = ( hash1[z] - hash1[y] * mu1[z - y] % mod1 + mod1 ) % mod1;

    long long aa = ( hash2[x] + hash2[y] - hash2[x] * mu2[y - x] % mod2 + mod2 ) % mod2;
    long long bb = ( hash2[z] - hash2[y] * mu2[z - y] % mod2 + mod2 ) % mod2;

    if ( ( s[x] != '0' || y - x == 1 ) && ( s[y] != '0' || z - y > 1 ) || aa == 0 && bb == 0 )
        if ( a == b && aa == bb && x && y > x && y < z )
        {
            // cout<<hash1[x]<<' '<<a<<' '<<b<<' '<<aa<<' '<<bb<<' '<<x<<' '<<y<<endl;
            show ( x, y, z );
        }

}
int main()
{
    while ( cin >> s )
    {
        mu1[0] = mu2[0] = 1;
        for ( long long i = 0; s[i]; i++ )
        {
            hash1[i + 1] = ( hash1[i] * base + s[i] - '0' ) % mod1;
            hash2[i + 1] = ( hash2[i] * base + s[i] - '0' ) % mod2;
            mu1[i + 1] = mu1[i] * 10 % mod1;
            mu2[i + 1] = mu2[i] * 10 % mod2;
        }
        long long len = s.size();
        long long pj = s.size() / 3;
        for ( int j = 1; j < len - 1; j++ )
        {
            int y;
            if ( ( len - j ) / 2 >= j )
                y = ( len - j ) / 2;
            else
                y = len - j * 2;
            if ( y >= 0 )
            {
                check ( j, j + y, len );
                check ( j, j + y + 1, len );
                check ( j, j + y - 1, len );
            }

        }

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值