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看懂题再补