KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200)

题目链接https://atcoder.jp/contests/abc200
A - Century
简单的abs(n-1)/100+1即可
B - 200th ABC-200
按题意写代码

点击查看代码
void solve(){
    int n,k;cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        if(n%200==0)n/=200;
        else n=n*1000+200;
    }
    cout<<n;

}
C - Ringo's Favorite Numbers 2 用MAP来存储 对于每个%200的数相加 规律为这个数如果相减的值%200为0 那么他们%200的值必定相等
点击查看代码
void solve(){
    int n,k;cin>>n;
    map<int,int>mp;
    vector<int>a(n);
    int sum=0;
    for(int i=0;i<n;i++){
        cin>>a[i];a[i]%=200;
        sum+=mp[a[i]];
        mp[a[i]]++;
    }
    cout<<sum;
}
D-Happy Birthday! 2 枚举子集 假设每个数都不相等那么如果超过8个数 将会有2^8=256种情况 根据鸽巢原理必定有解
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define pb push_back
#define pii pair<int,int>
using namespace std;
//const int mod=998244353;
//int qpw(int a,int b){int ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
//int inv(int x){return qpw(x,mod-2);}
const int maxn=1e6+10;
int dp[200];
unordered_map<int,vector<int>>mp;
void print(vector<int>v){
    cout<<v.size()<<" ";
    for(auto t:v)cout<<t<<" ";
    cout<<'\n';
}
void solve(){
    int n;cin>>n;vector<int>a(n);
    for(int i=0;i<n;i++)cin>>a[i];
    n=min(n,8ll);
    for(int i=1;i<(1<<n);i++){
        int sum=0;
        vector<int>ans;
        for(int k=0;k<n;k++){
            if(i>>k&1)sum+=a[k],ans.pb(k+1);
        }
        if(mp[sum%200].size()){cout<<"Yes\n";print(mp[sum%200]),print(ans);return;}
        else mp[sum%200]=ans;
    }
    cout<<"No\n";
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int _=1;
//    cin>>_;
    while(_--)solve();
}

补: E - Patisserie ABC 2 首先枚举取值情况 以s为例子 每个s都有s-1的空

根据高中所学的组合数学中的插排法可知存在C(s-1,2)种不同的情况即为(s-1)(s-2)/2
但是i j k的范围有限制
那么通过容斥定律进行容斥
我们使用隔板法求出每个情况的子集数
定义为int get(x) return (x-1)
(x-2)/2
将i j k的情况进行分类讨论
方案一为有一个元素的值大于n 那么我们将一个n提出 然后在剩下的元素中进行隔板法 最后再将提出的n加回 又因为有三个元素所以3 为get(s-n)3
方案二为有两个元素的值大于n 同理可得 这次有ij ik jk 三种情况 为get(s-2n)3
方案三为有三个元素的值大于n 这次仅有一种情况那么得出为get(s-3n)
根据容斥定律结果为t=get(s)-get(s-n)
3+get(s-2n)3-get(s-3*n)
对于k如果k>t那么对k-=t;
如果k<t那么就找到了所对应的s
接下来枚举i
对于每个i寻找它所对应的j的上下界
其中下界为宁外一个数取最大值即为max(s-n-i,1ll)
上界为另外一个数取最小即为min(s-n-1,n)
可取个数即为两数相减加一

点击查看代码
int get(int x){return x<=2?0:(x-1)*(x-2)/2;}
void solve(){
    int n,k;cin>>n>>k;
    for(int s=3;s<=n*3;s++){
        int t=get(s)-get(s-n)*3+get(s-2*n)*3-get(s-3*n);
        if(k>t){k-=t;continue;}
        for(int i=1;i<=n;i++){
            int mij=max(s-i-n,1ll),maj=min(s-i-1,n);
            if(mij>maj)continue;
            int num=maj-mij+1;
            if(k>num){k-=num;continue;}
            int j=mij+k-1;
            cout<<i<<" "<<j<<" "<<s-i-j;
            return;
        }
    }
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int _=1;
    while(_--)solve();
}
感谢观看
posted @ 2024-04-02 23:36  archer2333  阅读(54)  评论(0)    收藏  举报