CodeCraft-21 and Codeforces Round #711 (Div. 2)

🎈A - GCD Sum

题意

自定义gcd(n,n的每个数字之和),询问一个数字,大于等于第一个自定义gcd不等于1的数

思路

n是1e18,但是一般偶数的每个数字之和gcd==1,比如14 gcd(14,5),最多十位上加1,就有gcd不等于1的情况,所以直接暴力即可

AC代码

#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define ll long long
#define mod 1000000007
#define pb push_back
#define inf 0x3f3f3f3f
#define eps 0.00000001
const double pi = acos(-1);
using namespace std;
const int N=1e5+10;
inline ll sum(ll a){
    ll ans=0;
    while(a){
        ans+=a%10;a/=10;
    }
    return ans;
}
int main(){
    IOS;
    int t;
    ll n;
    cin>>t;
    while(t--){
        cin>>n;
        ll a=sum(n);
        while(__gcd(a,n)==1){
            n++;a=sum(n);
        }
        cout<<n<<endl;
    }
    return 0;
}

🎈B - Box Fitting

题意

给你n个长为2的幂,宽为1矩形(长度不会超过w),有一个长为w,宽无线长的空间,问最少这些矩形可以放多高

思路

很经典的贪心,一看去年省赛B题,首先的思路就是,你有n * m的空间,从大到小排序,每次挑选一个第一个大于等于空间放进去,把剩余的空间进行排序

但这样铁tle,所以我们用map优化,map是从小到大自动排好序的,直接用lower_bound就行了,有一个坑点就是mp[剩余空间]=0的时候,要把它erase掉,因为lower_bound也会算这个(自己可以尝试debug一下)

AC代码

#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define ll long long
#define mod 1000000007
#define pb push_back
#define inf 0x3f3f3f3f
#define eps 0.00000001
const double pi = acos(-1);
using namespace std;
const int N=1e5+10;
int a[N];
int main(){
    IOS;
    int t;
    cin>>t;
    while(t--){
        int n,m; cin>>n>>m;
        map<int,int>mp;
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        sort(a,a+n);
        mp[m]=n;
        int ans=0;
        for(int i=n-1;i>=0;i--){
            int pos=mp.lower_bound(a[i])->first;
            if(pos==m){ans++;}
            mp[pos]--;
            if(mp[pos]==0){mp.erase(pos);}
            mp[pos-a[i]]++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

🎈C - Planar Reflections

题意

有m块板,有一个n质量的小球。

小球一开始在最左边,向右边发射,每次接触板有两件事发生,第一件事就是会穿过板继续向同方向前行,第二件事就是会反弹向反方向前行,但质量会-1,直到质量为1的时候不反弹。

问最后有多少小球,取余

思路

一看到这题,铁dp,直接想出了状态转移方程,然后代码修修改改一小时过去了

这里因为有两个方向,所以我开了三维数组

有两个状态转移

从右到左边:dp[i][j][1]=(dp[i][j+1][1]+dp[i-1][j][0])(i表示球的质量,j表示板子之间的空间,1表示向左,0表示向右)

从左到右边:dp[i][j][0]=(dp[i][j-1][0]+dp[i-1][j][1])

求和 ∑ dp[i][m][0]+dp[i][0]1 即可

就是这个点往左都是被它的左边和(它的质量+1)的右边所影响,往右同理。所以方程式很好推。至于我为什么没写得这么快,忘记memset了

AC代码

#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof a)
#define pii pair<int,int>
#define ll long long
#define mod 1000000007
#define pb push_back
#define inf 0x3f3f3f3f
#define eps 0.00000001
const double pi = acos(-1);
using namespace std;
const int N=1e3+10;
ll dp[N][N][2];
int main(){
    IOS;
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>m>>n;
        mem(dp,0);
        if(n==1){
            cout<<"1"<<endl;continue;
        }
        for(int i=0;i<=m;i++){
            dp[1][i][0]=1;
        }
        for(int i=2;i<=n;i++){
            dp[i][m][1]=0;
            for(int j=m-1;j>=0;j--){
                dp[i][j][1]=(dp[i][j+1][1]+dp[i-1][j][0])%mod;
            }
            dp[i][0][0]=0;
            for(int j=1;j<=m;j++){
                dp[i][j][0]=(dp[i][j-1][0]+dp[i-1][j][1])%mod;
            }
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
           ans=(dp[i][m][0]+dp[i][0][1]+ans)%mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}

DE(又是交互题)F看懂题再补

posted @ 2021-03-31 13:11  ouluy  阅读(54)  评论(0编辑  收藏  举报