Codeforces Round #697 (Div. 3) ABCDE 题解

久违的cf服务器爆炸场

A. Odd Divisor

思路:任何一个数都可以写成(n = k2^m,其中k是一个奇数),若k=1,那么n就一定是一个2的幂。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

int main()
{
    int kase;
    cin>>kase;
    while(kase--)
    {
        ll n = read();
        int flag = 1;
        for(ll i=1; (1LL<<i)<=n; i++ )
        {
            if((1LL<<i)==n) flag = 0;
        }
        puts(flag?"YES":"NO");
    }
    return 0;
}


B. New Year's Number

思路:你知道答案肯定是(n = 2020i + 2021j)的形式,那么你只需要枚举i,看j是否存在即可。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

int main()
{
    int kase;
    cin>>kase;
    while(kase--)
    {
        ll n = read();
        int flag = 0;
        for(ll i=0; i*2020<=n; i++)
        {
            ll cur = n - i*2020;
            double num = cur/2021.0;
            if(num==(ll)num)
            {
                flag = 1;
                break;
            }
        }
        puts(flag?"YES":"NO");
    }
    return 0;
}

C. Ball in Berland

思路:因为只选出两组,我们只需要枚举其中一组的选法,另外一组就自然确定了。枚举a中每个人的舞伴时,当前贡献就是k - 和当前这个a有的舞伴个数 - 要和a跳舞的那个人的舞伴个数 + 本次的1, 画个图自己理解一下就很容易懂了。 最后答案要除2因为会有重复计算的对。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

vector<vector<ll> > a(maxn);
vector<vector<ll> > b(maxn);
ll ina[maxn];
ll inb[maxn];

int main()
{
    int kase;
    cin>>kase;
    int num = 1;
    while(kase--)
    {
        ll na = read(), nb = read(), k = read();

        for(int i=0; i<=na+2; i++)
        a[i].clear();
        for(int i=0; i<=nb+2; i++)
        b[i].clear();
        rep(i,1,k)  ina[i] = read();
        rep(i,1,k)  inb[i] = read();

        rep(i,1,k)
        {
            a[ina[i]].pb(inb[i]);
            b[inb[i]].pb(ina[i]);
        }
        ll ans = 0;
        rep(i,1,na)
        {
            for(int j=0; j<a[i].size(); j++)
            {
                ll cur = a[i][j];
                ans += k-a[i].size()-b[cur].size()+1;
            }
        }
        cout<<ans/2<<endl;
        num++;
    }
    return 0;
}


D. Cleaning the Phone

思路:破题口在于b只有两种情况,(bi=1或bi=2),那么我们可以采取前面B题的思路,答案肯定是选了x个bi=1的 + y个bi=2的, 由于贪心策略,我在这两种b的选择中,如果选k个,那肯定选a最大的那k个。 所以就只需要从大到小排序好,记录各自前缀和后,枚举一遍x,用二分看还需要多少个y,然后每次比较取最小即可。

view code
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include <queue>
    #include<sstream>
    #include <stack>
    #include <set>
    #include <bitset>
    #include<vector>
    #define FAST ios::sync_with_stdio(false)
    #define abs(a) ((a)>=0?(a):-(a))
    #define sz(x) ((int)(x).size())
    #define all(x) (x).begin(),(x).end()
    #define mem(a,b) memset(a,b,sizeof(a))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define rep(i,a,n) for(int i=a;i<=n;++i)
    #define per(i,n,a) for(int i=n;i>=a;--i)
    #define endl '
'
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> PII;
    const int maxn = 2e5+200;
    const int inf=0x3f3f3f3f;
    const double eps = 1e-7;
    const double pi=acos(-1.0);
    const int mod = 1e9+7;
    inline int lowbit(int x){return x&(-x);}
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
    inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
    inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
    inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
    inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
    int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

    ll a[maxn];
    ll b[maxn];
    ll suma[maxn];
    ll sumb[maxn];

    int main()
    {
        int kase;
        cin>>kase;
        while(kase--)
        {
            ll n = read(), m = read();
            rep(i,1,n) a[i] = read();
            rep(i,1,n) b[i] = read();
            vector<ll> one;
            vector<ll> two;
            rep(i,1,n)
            {
                if(b[i]==1) one.pb(a[i]);
                else two.pb(a[i]);
            }
            sort(one.begin(),one.end(), greater<ll>());
            sort(two.begin(),two.end(),greater<ll>());
            int lena = one.size();
            int lenb = two.size();
            rep(i,1,lena) suma[i] = suma[i-1] + one[i-1];
            rep(i,1,lenb) sumb[i] = sumb[i-1] + two[i-1];
            ll ans = 1e18;
            rep(i,0,lena)
            {
                ll One = suma[i];
                ll need = m - suma[i];
                if(need<=0)
                {
                    ans = min(ans,i);
                }
                else
                {
                    int id = lower_bound(sumb+1,sumb+1+lenb, need) - sumb;
                    if(id>lenb) continue;
                    ans = min(ans,id*2+i);
                }
            }
            if(ans==1e18) cout<<-1<<endl;
            else cout<<ans<<endl;
        }
        return 0;
    }


E. Advertising Agency

水题,预处理一下组合数就行了。我肯定挑的是最大的那k个,每次的贡献就是ans = ans*C(a[i]的个数,要挑出的个数)。

view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '
'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

ll dp[1005][1005];
ll a[maxn];

void init()
{
    rep(i,0,1003) dp[i][0] = 1;
    rep(i,1,1003) rep(j,1,1003) dp[i][j] = (dp[i-1][j-1] + dp[i-1][j])%mod;
}

int main()
{
    init();
    int kase;
    cin>>kase;
    while(kase--)
    {
        map<ll,ll> Map;
        ll n = read(), k =  read();
        rep(i,1,n) a[i] = read(), Map[a[i]]++;
        sort(a+1,a+1+n);
        ll pre = -1;
        ll ans = 1;
        per(i,n,1)
        {
            if(a[i]==pre) continue;
            ll d = min(k,Map[a[i]]);
            ans = ((ans%mod)*(dp[Map[a[i]]][d]%mod))%mod;
            k -= d;
            pre = a[i];
        }
        cout<<ans<<endl;
    }
    return 0;
}


原文地址:https://www.cnblogs.com/Bgwithcode/p/14329357.html