Codeforces Round #674 (Div. 3)(A->D(前缀和出现次数))

A:http://codeforces.com/contest/1426/problem/A

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+50;
int a[maxn];
int vis[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,x;
        cin>>n>>x;
        if(n<=2)
            cout<<"1"<<endl;
        else
        {
            if(n<=x)
                cout<<"2"<<endl;
            else
                {
                    int md=(n-2)/x;
                    if((n-2)%x!=0)
                        md++;
                    cout<<md+1<<endl;
                }
        }
    }
}

B:http://codeforces.com/contest/1426/problem/B

题意:

n种2*2的砖头,数量不限,是否能恰好铺满m*m的格子,砖块不可出界。

解析:

很明显,m奇数时一定不行。

只要存在一种砖块:左下角等于右上角即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e2+50;
int a[maxn];
int vis[maxn];
struct node
{
    int x,y;
}st[maxn];
int mp[maxn][maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
         int n,m;
         cin>>n>>m;
         int ok=0,cnt=0;
         for(int i=1;i<=2*n;i+=2)
         {
             for(int j=1;j<=2;j++)
             {
                 for(int c=1;c<=2;c++)
                     cin>>mp[j][c];                     
            }
            if(mp[1][1]==mp[2][2]&&mp[2][1]==mp[1][2])
            {
                ok=1;
            }
            if(mp[1][2]==mp[2][1])
                cnt++;
        }
        if(m%2)
        {
            cout<<"NO"<<endl;
            continue;
        }
        if(ok||cnt>=1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
}

C:http://codeforces.com/contest/1426/problem/C

题意:

原始数组{1},可以对其某个数+1,或者复制一个。

使得总和>=n的最小操作数。

解析:

列了一会,发现很复杂,一个数可能来自于前面某个数的复制。

所以考虑这么一种方法:原始1自增到某个值x,然后一直复制自己d次,直到>=n

那么有x*d==n,如果让x+d最小,则x==d==sqrt(n)

所以枚举到根号n即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+50;
const int inf=1e9;
int a[maxn];
int b[maxn];
int d[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n;
        cin>>n;
        ll minn=inf;
        for(int i=1;i*i<=n;i++)
        {
            ll md=(n-i)/i;
            if((n-i)%i!=0)
                md++;
            minn=min(minn,i-1+md);
        }
        cout<<minn<<endl;
    }
}

D:http://codeforces.com/contest/1426/problem/D

题意:

可以在数组的任意位置插入一个无穷大/无穷小/0

使得不存在子数组和为0的最小操作数。

解析:

很容易想到前缀和。

如果sum[i]==sum[j],那么i+1~j这一段的和为0。

插入一个最大值,为了让操作数最小,放的时候跨度需要大一些。很明显,放到a[j]右边不合适,所以放到a[j]左边。

那么,由于最大值的存在,j之前的数,无论如何都不可能出现和为0。所以前面的就可以忽略,全新的前缀和记录从a[j]开始。map进行清0。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
const int inf=1e9;
ll a[maxn];
int main()
{
    ll n;
    cin>>n;
    ll sum=0;
    map<ll,bool>mp;
    mp[0]=true;    
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
        if(mp.count(sum))
        {
            cnt++;
            sum=a[i];
            mp.clear();
            mp[0]=true;
            mp[sum]=true;
        }
        else
        {
            mp[sum]=true;
        }
    }
    cout<<cnt<<endl;
}
原文地址:https://www.cnblogs.com/liyexin/p/13759429.html