A. GCD Sum
签到题 直接求就好了 没啥好说的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxt=1000;
int t;
ll n;
bool isprime(ll x,ll y){//求最小公因数
if(x==1&&y==1) return true;
int temp;
while(true){
temp=x%y;
if(temp==0){
break;
}
else {
x=y;
y=temp;
}
}
if(y==1) return true;
else return false;
}
int main()
{
cin>>t;
while(t --){
scanf("%lld",&n);
ll cnt;
while(1){
ll r=0;
cnt=n;
while(cnt){
r+=cnt%10;
cnt /=10;
}
if(isprime(r,n)!=1) {
cnt=n;
break;
}
else n++;
}
printf("%lld\n",cnt);
}
return 0;
}
B. Box Fitting
优先队列 贪心
使用优先队列这道题就会变得十分简单
每次都枚举一个宽度为w的长度到优先队列里面 然后从大到小给所有的长方形进行排序 构造一个循环
每次将一个长方形的宽度与优先队列里的w作比较 如果小于这个w 则说明在这一层可以放下 并且剩余宽度为w减掉这个长方形的宽度 如果放不下 就要再输入一个w到优先队列里面 也就是高度会加一
你可以把优先队列里面的节点当作一的高度 有多少个节点 就说明 需要多高的高度
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxt=1e5+10;
ll t,h[maxt];
bool cmp(ll a,ll b){
return a>b;
}
int main()
{
cin>>t;
while(t --){
ll n,w;
scanf("%lld %lld",&n,&w);
for(int i=0;i <n;i ++)
scanf("%lld",&h[i]);
sort(h,h+n,cmp);
priority_queue<int> q;//优先队列
for(int i=0;i <n;i ++){
if(q.empty()){
q.push(w);
}
if(q.top()<h[i]){
q.push(w-h[i]);
}
else {
int now=q.top();
q.pop();
q.push(now-h[i]);
}
}
cout<<q.size()<<endl;
}
return 0;
}
priority_queue<int> q 优先队列 其用法与队列完全相同
但是会给队列中的节点进行排序 默认是从大到小进行排序
队列中的节点是按照降序排序的
如果想按照升序排序的话 可以写成
priority_queue<int,vector<int>,greater<int>> q;
如果存入的是字符串则会按照字典序排序
C. Planar Reflections
dp题 就是要注意几个细节
设h[i][j] 表示为这个粒子前面有i个平面 质量为j会产生多少个粒子;
每当它穿过一个平面的时候 就会产生一个粒子h[n-i][j-1] 也就是那个相反方向的副本粒子 它需要穿过 n - i 个平面 并且质量会减一
还会产生一个粒子h[i-1][j] 也就是平面数减一 质量不变的粒子
当质量为1的时候 总是产生一个粒子 h[i][1]=1;
当平面为0的时候 总是产生一个粒子 h[0][j]=1;
综上就可以得出 dp表达式
h[i][j]=(h[n-i][j-1],h[i-1][j]);
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int maxt=1e3+10;
const ll mod=1e9+7;
int t,n,k;
ll h[maxt][maxt];
//h[i][j] 表示某个粒子前面有i层平面 质量为j
int main()
{
cin>>t;
while(t --){
scanf("%d %d",&n,&k);
for(int i=0;i <=n;i ++) h[i][1]=1;
for(int i=1;i <=k;i ++) h[0][i]=1;
for(int j=1;j <=k;j ++)//注意需要先枚举j质量 再枚举i平面
for(int i=1;i <=n;i ++)
h[i][j]=(h[n-i][j-1]+h[i-1][j])%mod;
/*for(int i=1;i <=n;i ++)
for(int j=1;j <=k;j ++)
h[i][j]=(h[n-i][j-1]+h[i-1][j])%mod;*/
/*for(int i=1;i <=n;i ++){
for(int j=1;j <=k;j ++){
cout<<h[i][j]<<" ";
}
cout<<endl;
} */
cout<<h[n][k]<<endl;
}
return 0;
}
在这道题目里面为什么要先枚举j质量 再枚举i平面呢?
谁先开始不都是一样的吗 都是枚举那么多次。
其实不然 因为我们这个dp表达式为h[i][j]=(h[n-i][j-1],h[i-1][j]);
当你要求h[3][3] 的值的时候 我们是从h[1][1]开始枚举的 如果我们先以i开始枚举的话 那下一个就是要求h[1][2] 当我们要求这个的时候 也就是 h[1][2]=(h[2][1],h[0][2]) 可是这时候的h[2][1]我们还没有枚举到啊
因为这时候是一层一层开始枚举的 所以这样是会出错的
因此我们需要从j开始枚举 也就是一列一列开始枚举 这样就不会出错了
对于这次的cf 我感觉自己发挥的不是很好 又是只写了一道题(真的垃圾)
多说无益 自己好好努力吧!