打完蓝桥以为自己要退役了于是摆了一个月 还掉回newbee了 结果居然还进了 那这个半个月再努力冲回pupil吧
Codeforces Round 943 (Div. 3)
A. Maximize?
签到题 范围只到1000 闭着眼睛遍历就行
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int uy=0,m=0;
for(int i=1;i<n;i++)
{
int now=__gcd(i,n);
if(now+i>m)
{
m=now+i;
uy=i;
}
}
printf("%d\n",uy);
}
return 0;
}
B. Prefiquence
子串不需要连续,那么就对a串的每一个字母在b里面找对应,不回头扫完一遍就可以了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
string a;
string b;
cin>>a;
cin>>b;
int i=0,j=0;
int cnt=0;
for(;j<m;i++)
{
while(b[j]!=a[i]&&j<m)
{
j++;
}
if(j>=m)
break;
if(i>=n)
break;
cnt++;
j++;
}
printf("%d\n",cnt);
}
return 0;
}
C. Assembly via Remainders
一开始是直接加上去的 后来发现不太对 所以每次加之前控制乘n倍使得比下一个数大 就可以直接加上去了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int x[n+1];
for(int i=2;i<=n;i++)
{
scanf("%d",&x[i]);
}
int a[n+1];
a[1]=x[2]+1;
printf("%d ",a[1]);
for(int i=2;i<=n;i++)
{
int t=0;
if(i<n)
t=x[i+1]/a[i-1];
t++;
a[i]=a[i-1]*t+x[i];
printf("%d ",a[i]);
}
printf("\n");
}
return 0;
}
D. Permutation Game
跟博弈没啥关系,两个人各走各的比较大小就行,考虑模拟
但是模拟的话k是1e9肯定会超时,发现对于p数组走n次不停留一定能回到起始点,所以其实n次内找到一个合适的地点一直在那呆着就行,所以如果k比n大只需要遍历到n就行
具体模拟就是开一个ans每次遍历所有可能走到的点,比较在这个点一直呆到最后的ans和之前ans的值每次取最大更新就行。最后两个人的数字比较输出答案即可。
记得开long long
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k,pb,ps;
scanf("%d%d%d%d",&n,&k,&pb,&ps);
int p[n+1],a[n+1];
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
long long sb=0,ss=0;
long long nowb=0,nows=0;
for(int i=1,npb=pb,nps=ps;i<=n&&i<=k;i++)
{
nowb+=a[npb];nows+=a[nps];
sb=max(sb,nowb+(long long)(k-i)*a[npb]);
ss=max(ss,nows+(long long)(k-i)*a[nps]);
npb=p[npb];nps=p[nps];
}
if(sb==ss)
printf("Draw\n");
else if(sb>ss)
printf("Bodya\n");
else
printf("Sasha\n");
}
return 0;
}
E. Cells Arrangement
这题真的很恶心 将奇偶分开看 发现如果对角线全填然后挪动一个就可以实现曼哈顿距离全覆盖 所以代码也就出来了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
printf("1 1\n1 2\n");
for(int i=3;i<=n;i++)
{
printf("%d %d\n",i,i);
}
}
return 0;
}
Codeforces Round 723 (Div. 2)
包上强度的 开始VP
A. Mean Inequality
对给定的数组重排列使得任何数都不是左右两个数的平均数
一个最大一个最小交叉排列即可
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[2*n+1];
for(int i=1;i<=2*n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+2*n+1);
for(int i=1;i<=n;i++)
{
printf("%d %d ",a[i],a[2*n+1-i]);
}
printf("\n");
}
return 0;
}
B. I Hate 1111
很容易想到贪心 从大到小一个一个除下来就行
#include <bits/stdc++.h>
using namespace std;
int all[10]={11,111,1111,11111,111111,1111111,11111111};
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=6;i>=0;i--)
{
n%=all[i];
}
if(n==0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
但是WA2了 发现有的数可以用小的凑出来 但是减掉大的之后反而不行了
那就不能贪心 考虑DP 但是想到一半发现还是没必要 因为从1111往后的数字都可以用11和111表示出来 那么就变成了求a*11+b*111=x有没有整数解 考虑拓展欧几里得
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int tmp=n%11;
tmp*=111;
if(tmp<=n)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
C. Potions
一开始是非常猪鼻的想把正数全加起来计数然后WA了一发
找到问题之后就改成这样 先假设全部喝掉了 然后开始遍历 血量少于0就吐出来一瓶 这里需要用到优先队列简化代码 不过用数组每次循环里面sort一下应该问题也不大
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
//scanf("%d",&T);
while(T--)
{
int n;
scanf("%lld",&n);
int a[n];
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
priority_queue <int,vector<int>,greater<int> > q;
int ans=n;
int now=0;
for(int i=0;i<n;i++)
{
now+=a[i];
q.push(a[i]);
if(now<0)
{
ans--;
int re=q.top();
now-=re;
q.pop();
}
}
printf("%lld\n",ans);
}
return 0;
}
Codeforces Round 882 (Div. 2)
继续上强度好吧
A. The Man who became a God
可以把一个数组切成k段 使得每一段的相邻两数之差之和之和最小(听起来很绕是吧)
其实就是遇到特别大的相邻差就断开一下把他变成0 直接开一个数组存所有相邻差然后排序 把最大的k-1个去掉就行
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n, k;
scanf("%d%d",&n,&k);
int a[n];
for(int i = 0; i < n; i++)
scanf("%d",&a[i]);
int b[n];
for(int i = 0; i + 1 < n; i++)
b[i]=abs(a[i]-a[i+1]);
sort(b,b+n-1);
int ans = 0;
for(int i = 0; i < n - k; i++)
ans += b[i];
printf("%d\n",ans);
}
}
B. Hamon Odyssey
又是我知识储备几乎为0的二进制 这场对我来说属实不太友好啊
在确保每一段与值之和保持最小的同时问最多能分成多少段
如果原数列到不了0那就不能分 分了就会变大 输出1
否则就每次0的位置断一下 因为只要到0了就不会变大了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[n];
int ans=INT_MAX;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
ans&=a[i];
}
if(ans!=0)
printf("1\n");
else
{
ans=INT_MAX;
int cnt=0;
for(int i=0;i<n;i++)
{
ans&=a[i];
if(ans==0)
{
ans=INT_MAX;
cnt++;
}
}
printf("%d\n",cnt);
}
}
return 0;
}
C. Vampiric Powers, anyone?
又是个异或 难受啊 开始补题 边学边写吧
选任何一个位置 从这里一直取到最后连续求异或得到一个值 将这个值放在原数组最右端 问操作任意次之后可能得到的数组内最大值
得益于我贫瘠的知识储备 我真的是一点思路都没有 甚至一度认为这个值真的是存在的嘛
在看了这里的推导后 我知道这个值是存在的 只要求最大的子串异或和就可以了
既然现在的问题是求最大子串异或和 那干脆用异或前缀和试一下不就行了
(这个代码顺便挑战了一下改成队长的mordern马蜂)
#include <bits/stdc++.h>
void slove(){
int n;
scanf("%d",&n);
int a[n+1],s[n+1]={0};
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i]=s[i-1]^a[i];
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int now=s[j]^s[i-1];
ans=std::max(now,ans);
}
}
printf("%d\n",ans);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
slove();
}
return 0;
}
当然是不负众望地TLE了 看一眼数据范围发现n是1e5那确实不能套两层循环 但是这个时候看到一个特别显眼的值 a只到256诶 那我们就开个桶吧
(最后过了的代码长这个样子)
#include <bits/stdc++.h>
void slove(){
int n;
scanf("%d",&n);
int a[n+1],s[n+1]={0};
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i]=s[i-1]^a[i];
}
int barrel[500]={0};
int ans=0;
for(int i=0;i<=n;i++){
barrel[s[i]]++;
}
for(int i=0;i<=n;i++){
for(int j=0;j<256;j++){
if(barrel[j]>0) ans=std::max(ans,s[i]^j);
}
}
printf("%d\n",ans);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
slove();
}
return 0;
}
【LGR-183-Div.3】复旦勰码基础赛 #10 & QFOI Round 2
还是做一做洛谷换换脑子吧 顺便再冲一下洛谷的橙名
U420199 「QFOI R2」水落溪流浅浅
签到题 舒服了
#include <iostream>
using namespace std;
int main()
{
int h,m;
scanf("%d:%d",&h,&m);
if(h>=6&&h<=23)
printf("%02d:%02d",h,m);
else if(h==23&&m<=59)
printf("%02d:%02d",h,m);
else
{
h+=24;
printf("%02d:%02d",h,m);
}
return 0;
}
U420200 「QFOI R2」寺秋山霭苍苍
精度是0.0001范围最大是0到1那就直接遍历 最多也就跑1000次嘛
#include <bits/stdc++.h>
double distance(double x1, double y1, double x2, double y2)
{
return std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
double triangle_area(double a, double b, double c)
{
double p = (a + b + c) / 2;
return std::sqrt(p * (p - a) * (p - b) * (p - c));
}
double calculateNewPointX(double x1, double x2, double p)
{
return x1 + p * (x2 - x1);
}
double calculateNewPointY(double y1, double y2, double p)
{
return y1 + p * (y2 - y1);
}
double find_min_area(double l, double r, double x1, double y1, double x2, double y2, double x3, double y3)
{
double t = distance(x1, y1, x2, y2);
double k = distance(x2, y2, x3, y3);
double o = distance(x3, y3, x1, y1);
double min_area = triangle_area(t,k,o); // 初始化最小面积为最大值
double best_p = 0.0; // 记录使面积最小的p值(虽然题目不要求)
for (double p = l; p <= r; p += 0.0001)
{
// 计算新点D、E、F的坐标
double xD = calculateNewPointX(x1, x2, p);
double yD = calculateNewPointY(y1, y2, p);
double xE = calculateNewPointX(x2, x3, p);
double yE = calculateNewPointY(y2, y3, p);
double xF = calculateNewPointX(x3, x1, p);
double yF = calculateNewPointY(y3, y1, p);
// 计算三角形DEF的边长
double a = distance(xD, yD, xE, yE);
double b = distance(xE, yE, xF, yF);
double c = distance(xF, yF, xD, yD);
// 计算三角形DEF的面积
double area = triangle_area(a, b, c);
//printf("%d\n",p);
if (area < min_area)
{
min_area = area;
best_p = p;
}
//printf("%.5lf\n",best_p);
}
return min_area;
}
int main()
{
double l, r, x1, y1, x2, y2, x3, y3;
std::cin >> l >> r >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
double min_area = find_min_area(l, r, x1, y1, x2, y2, x3, y3);
printf("%.12lf",min_area);
return 0;
}
Codeforces Round 942 (Div. 2)
继续P继续P
A. Contest Proposal
从小到大扫一遍 不满足题意就改最后一个数再sort一下就行 因为只有100所以随便过
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[n],b[n];
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&b[i]);
int cnt=0;
for(int i=0;i<n;i++)
{
if(a[i]>b[i])
{
cnt++;
a[n-1]=b[i];
sort(a,a+n);
}
}
printf("%d\n",cnt);
}
return 0;
}
B. Coin Games
直接数有几个硬币在正面 奇数YES偶数NO就行了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
string s;
cin>>s;
int cnt=0;
for(int i=0;i<n;i++)
{
if(s[i]=='U')
cnt++;
}
if(cnt%2!=0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
D1. Reverse Card (Easy Version)
简单转化之后遍历就行 数据范围很小
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int n,m;
scanf("%lld%lld",&n,&m);
int ans=0;
for(int b=1;b<=m;b++)
{
int a=b;
while(a<=n)
{
if((a+b)%(b*b)==0)
ans++;
a+=b;
}
}
printf("%lld\n",ans);
}
return 0;
}
C. Permutation Counting
赛时题意理解有点小问题 一位必须是按照顺序的序列才算所以写成了这个样子
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int n,m;
scanf("%lld%lld",&n,&m);
int ans=0;
for(int b=1;b<=m;b++)
{
int a=b;
while(a<=n)
{
if((a+b)%__gcd(a,b)==0)
ans++;
a+=b;
}
}
printf("%lld\n",ans);
}
return 0;
}
但是如果是任意顺序的话我好像确实就有点盘不出来了 于是就直接补题来了
不过发现有一个公式 模拟的方式其实没太大变化 只是结果的计算不太一样 修改一下即可
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int n,k;
scanf("%lld%lld",&n,&k);
int a[n+1],b[n+1];
for(int i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
b[i]=a[i];
}
if(n==1)
printf("%lld\n",a[1]+k);
else
{
sort(a+1,a+1+n);
int ans=0,sum=0;
for(int i=1; i<n; i++)
{
if((a[i+1]-a[i])*i<=k)
{
k-=(a[i+1]-a[i])*i;
ans=a[i+1];
}
else
{
int u=k/i;
k-=u*i;
ans=a[i]+u;
break;
}
}
sum+=(ans*n-n+1);
int l=0;
for(int i=1; i<=n; i++)
{
if(b[i]<=ans&&k==0)
l++;
else if(b[i]<=ans&&k!=0)
k--;
}
sum+=(n-l+k);
printf("%lld\n",sum);
}
}
return 0;
}
Codeforces Round 640 (Div. 4)
主要是熟悉下队长的mordern码风顺便看看能不能AK一把
A. Sum of Round Numbers
拆数字带一下计数就行 签到
#include <bits/stdc++.h>
void solve()
{
std::string s;
std::cin>>s;
int cnt=0;
int l=s.length();
for (int i=0;i<l;i++)
{
if (s[i]=='0')
continue;
else
cnt++;
}
printf("%d\n",cnt);
for (int i=0;i<l;i++)
{
if (s[i]=='0')
continue;
else
{
printf("%c",s[i]);
for (int j=i+1;j<l;j++)
printf("0");
printf(" ");
}
}
printf("\n");
}
int main()
{
int t=1;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
B. Same Parity Summands
其实要么拆成一大堆1和一个奇数要么就拆成一大堆2和一个偶数就行
#include <bits/stdc++.h>
void solve(){
int n,k;
scanf("%d%d",&n,&k);
if((n-k+1)%2==1){
printf("YES\n");
for(int i=1;i<k;i++){
printf("1 ");
}
printf("%d\n",(n-k+1));
return ;
}
else if((n-2*k+2)%2==0&&(n-2*k+2)>0){
printf("YES\n");
for(int i=1;i<k;i++){
printf("2 ");
}
printf("%d\n",(n-2*k+2));
return ;
}
else{
printf("NO\n"); return ;
}
}
int main(){
int t=1;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}
C. K-th Not Divisible by n
其实每数到n的倍数就抠一个数就行 所以直接模n-1就知道数了几轮了
#include <bits/stdc++.h>
using i64=long long;
void solve(){
i64 n,k;
scanf("%lld%lld",&k,&n);
i64 tmp=n/(k-1);
i64 ans=tmp*k+n%(k-1);
if(ans%k==0) ans--;
printf("%lld\n",ans);
}
int main()
{
int t=1;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}
D. Alice, Bob and Candies
按照题意模拟即可
#include <bits/stdc++.h>
using i64=long long;
void solve(){
int n,i,j,cnt,sum,p,A,B;
std::cin>>n;
int a[n+1];
for(i=1;i<=n;i++)
std::cin>>a[i];
cnt=A=B=p=0;
for(i=1,j=n;i<=j;)
{
sum=0;
for(;i<=j&&sum<=p;i++)
sum+=a[i];
if(i<=j)
cnt+=2;
else
cnt++;
A+=sum;
p=sum;
sum=0;
for(;i<=j&&sum<=p;j--)
sum+=a[j];
B+=sum;
p=sum;
}
std::cout<<cnt<<' '<<A<<' '<<B<<std::endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t=1;
std::cin>>t;
while(t--){
solve();
}
return 0;
}
E. Special Elements
一开始把题意理解错了 以为是任意两个数加起来就行
#include <bits/stdc++.h>
using i64=long long;
void solve(){
int n;
scanf("%d",&n);
int bow[n+1]={0};
for(int i=0;i<n;i++){
int c;
scanf("%d",&c);
bow[c]++;
}
int cnt[n+1]={0};
for(int i=1;i<=n;i++){
if(bow[i]>=2){
if(bow[i*2]>0) cnt[i*2]++;
}
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(bow[i+j]>=1) cnt[i+j]++;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(cnt[i]>0) ans++;
}
printf("%d\n",ans);
}
int main()
{
int t=1;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}
因为数据范围很小 所以前缀和再开个桶计算就可以了
#include <bits/stdc++.h>
using i64=long long;
void solve(){
int n;
scanf("%d",&n);
int a[n+1]={0};
int bow[n+1]={0};
for(int i=1;i<=n;i++){
int c;
scanf("%d",&c);
a[i]=a[i-1]+c;
bow[c]++;
}
int ans=0;
for(int i=0;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(bow[a[j]-a[i-1]]>0) ans+=bow[a[j]-a[i-1]];
}
}
printf("%d\n",ans);
}
int main()
{
int t=1;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}
Educational Codeforces Round 165 (Rated for Div. 2)
现在每天不打VP就浑身难受啊
A. Two Friends
其实不难看出最多拉三个人就一定有两个人应邀 所以只需要考虑什么时候拉两个人即可 也很容易看出来就是两个人双向奔赴的时候把两个人打包带走就行
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[n+1];
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int ans=3;
for(int i=1;i<=n;i++){
if(a[a[i]]==i)
{
ans=2;
break;
}
}
printf("%d\n",ans);
}
return 0;
}
B. Shifts and Sorting
先分析下移动方式优化模拟方式 其实就是连续i个1移动k格则需要消耗(i+1)*k的积分
再想想怎么向右移动积分最少 要么就是从右往左每一片1一个一个移到最后面 要么就是从左往右每片1都漂洋过海和下一片1汇合再一起到最右边
样例带进去或者简单推一下 如果使用前者的话因为公式里面+1的存在 除了最后一片的每一个1都要多消耗k的积分 所以不可取 取后者 最后记得开long long(是的我WA了3发)
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
string s;
cin>>s;
int l=s.length();
int counting=0;
int jxj=0;
int ans=0;
for(int i=0;i<l;i++)
{
if(s[i]=='0')
{
counting++;
if(i==l-1||s[i+1]=='1')
{
if(jxj>0)
ans+=(jxj+1)*counting;
counting=0;
}
}
else
{
jxj++;
}
}
printf("%lld\n",ans);
}
return 0;
}
C. Minimizing the Sum
dp没学好 赛时觉得O(n*k)好像不是不能接受所以写的是这么个贪心
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int n,k;
scanf("%lld%lld",&n,&k);
int a[n+2]={0};
a[0]=1e9;
a[n+1]=1e9;//多开两个省得边缘特判
int b[n+1]={0};
int sum=0;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum+=a[i];
}
if(n==1)
{
printf("%lld\n",sum);
continue;
}
sum=0;
for(int i=1;i<=n;i++){
b[i]=max(a[i]-a[i+1],a[i]-a[i-1]);
}
for(int j=0;j<k;j++)
{
int m=0,p=0;
for(int i=1;i<=n;i++)
{
if(b[i]>m)
{
m=b[i];
p=i;
}
}//这个其实就是找最大值的位置嘛
if(b[p]<=0)
break;//一定注意动不了了就要及时止损
a[p]=min(a[p-1],a[p+1]);
b[p]=0;
b[p-1]=max(a[p-1]-a[p],a[p-1]-a[p-2]);
b[p+1]=max(a[p+1]-a[p],a[p+1]-a[p+2]);
/*printf("j=%lld:\n",j);
for(int i=1;i<=n;i++) printf("%lld ",a[i]);
printf("\n");
for(int i=1;i<=n;i++) printf("%lld ",b[i]);
printf("\n");*/
}
for(int i=1;i<=n;i++) sum+=a[i];
printf("%lld\n",sum);
}
return 0;
}
然后WA2并被群友无情hack了
感谢群友的思路 (好像是)学会了
开一个二维dp[i][j]表示到考虑第i个数,允许操作j次得到的最小总和
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
int a[n+1]={0};
int dp[n+1][k+1]={0};
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
dp[i][0]=dp[i-1][0]+a[i];//一次不操作那就是前缀和嘛
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
dp[i][j]=min(dp[i][j],dp[i-1][j]+a[i]);//如果什么事都不做那就只是加上去而已
int now=a[i];
for(int o=1;o<=min(i-1,j);o++){
now=min(now,a[i-o]);//找最近这些格内的最小值
dp[i][j]=min(dp[i][j],dp[i-o-1][j-o]+(o+1)*now);
}
}
}
int ans=INT_MAX;
for(int i=1;i<=k;i++) ans=min(ans,dp[n][i]);
printf("%d\n",ans);
}
return 0;
}
Codeforces Round 944 (Div. 4)
挑战AK再失败 可能是因为两天没VP了吧 不过还是成功Pupil了
A. My First Sorting Problem
多说一个字都是对这道题的巨大高估
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int a,b;
cin>>a>>b;
cout<<min(a,b)<<' '<<max(a,b)<<endl;
}
return 0;
}
B. Different String
只要字符串不是全部由同一个字符组成的就行了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
string s;
cin>>s;
int l=s.length();
int flag=0;
for(int i=0;i<l-1;i++)
{
if(s[i]!=s[i+1])
{
flag=1;
swap(s[i],s[i+1]);
break;
}
}
if(flag)
{
printf("YES\n");
cout<<s<<endl;
}
else
{
printf("NO\n");
}
}
return 0;
}
C. Clock and Strings
看起来好像要判断套很多层 其实只需要分内外就可以了 有一侧是一定满足a<x<b的 那另一侧自然就一个else搞定了
#include <bits/stdc++.h>
using namespace std;
int check(int a,int b,int c)
{
if(min(a,b)<c&&c<max(a,b))
return 1;
return -1;
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
if(check(a,b,c)==check(a,b,d))
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
D. Binary Cut
先看错题了 以为必须两个两个切
题目本身还是比较一眼的 因为t和|s|都很小 所以直接遍历所有01的位置把他们前后的所有能加进一段的全变成'3' 然后每次遍历跑一遍就行
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
string s;
cin>>s;
int l=s.length();
int ans=1e9;
for(int now=1; now<l; now++)
{
if(s[now]=='1'&&s[now-1]=='0')
{
string tmp=s;
for(int i=now-1; i>=0; i--)
{
if(tmp[i]!='0')
break;
tmp[i]='3';
}
for(int i=now; i<l; i++)
{
if(tmp[i]!='1')
break;
tmp[i]='3';
}
int lmt=1;
for(int i=1; i<l; i++)
{
if(tmp[i]!=tmp[i-1])
{
lmt++;
}
}
ans=min(lmt,ans);
}
}
int lmt=1;
for(int i=1; i<l; i++)
{
if(s[i]!=s[i-1])
{
lmt++;
}
}
ans=min(lmt,ans);
printf("%d\n",ans);
}
return 0;
}
E. Find the Car
这题一开始没看到q的范围觉得好简单 就是个大模拟遍历嘛 然后TLE7了
#include <bits/stdc++.h>
using i64 = long long;
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k,q;
scanf("%d%d%d",&n,&k,&q);
int a[k+2]={0};
i64 b[k+2]={0};
for(int i=1;i<=k;i++) scanf("%d",&a[i]);
for(int i=1;i<=k;i++)
{
i64 c;
scanf("%lld",&c);
b[i]=c;
}
b[k+1]=LONG_MAX;
int question[q];
for(int i=0;i<q;i++) scanf("%d",&question[i]);
for(int i=0;i<q;i++)
{
int d=question[i];
int p=0;
for(int i=0;i<=k;i++)
{
if(a[i]<=d&&a[i+1]>=d)
{
p=i;
break;
}
}
if(a[p]==d)
{
printf("%lld ",b[p]);
}
else if(a[p+1]==d)
{
printf("%lld ",b[p+1]);
}
else
{
i64 ans=b[p];
double lil=((double)b[p+1]-b[p])*((double)d-a[p])/((double)a[p+1]-a[p]);
ans+=lil;
//printf("ans=%lld lil=%.2lf\n",ans,lil);
printf("%lld ",ans);
}
}
printf("\n");
}
return 0;
}
但是没想起来二分 强行开结构体排序所有d然后把a[]遍历一遍居然过了(最后四分钟极限过题) 不过这个写法还是很有风险的 虽然好像是没被hack
#include <bits/stdc++.h>
using i64 = long long;
using namespace std;
struct band
{
int d;
int pos;
};
bool cmp(band a,band b)
{
return a.d<b.d;
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k,q;
scanf("%d%d%d",&n,&k,&q);
int a[k+2]= {0};
i64 b[k+2]= {0};
for(int i=1; i<=k; i++) scanf("%d",&a[i]);
for(int i=1; i<=k; i++)
{
i64 c;
scanf("%lld",&c);
b[i]=c;
}
b[k+1]=LONG_MAX;
band question[q];
for(int i=0; i<q; i++)
{
scanf("%d",&question[i].d);
question[i].pos=i;
}
sort(question,question+q,cmp);
//for(int i=0; i<q; i++) printf("%d",question[i].d);
int i=0;
i64 ans[q]={0};
for(int j=0;j<=k;1)
{
if(a[j]<=question[i].d&&a[j+1]>=question[i].d)
{
i64 ans12=b[j];
double lil=((double)b[j+1]-b[j])*((double)question[i].d-a[j])/((double)a[j+1]-a[j]);
ans[question[i].pos]=ans12+lil;
i++;
}
else
j++;
if(i==q)
break;
}
for(int i=0;i<q;i++)
printf("%lld ",ans[i]);
printf("\n");
}
return 0;
}
(群友锐评)
最后再补一个这位群友的二分+map吧(反正我懒得写了)
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#define int long long
const int N = 1e6;
int a[N],b[N];
signed main()
{
int t;
std::cin >> t;
while(t--)
{
int n,k,p;
std::cin >> n >> k >> p;
for(int i = 1 ; i <= k ; i ++) std::cin >> a[i];
for(int i = 1 ; i <= k ; i ++) std::cin >> b[i];
std::map<int,int> mp;
for(int i = 0 ; i <= k ; i ++) mp[a[i]] = b[i];
while(p--)
{
int f;
std::cin >> f;
if(f == 0) std::cout << 0 << " ";
else
{
int* q = std::lower_bound(a,a+k+1,f);
std::cout << (int)((f-*(q-1))*(mp[*(q)]-mp[*(q-1)])/(*(q)-*(q-1)) + mp[*(q-1)] + 0.5) << " ";
}
}
std::cout << "\n";
}
return 0;
}
F. Circle Perimeter
其实还是遍历 但是k²肯定不行 扫一遍r就可以 然后y拿公式算
(又被压力了)
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int r;
scanf("%lld",&r);
int ans=0;
for(int x=-r;x<=r;x++)//遍历范围内所有x
{
int y=ceil(sqrtl(r*r-x*x));
int dy=sqrtl((r+1)*(r+1)-x*x-1);//减一解决开闭区间问题
ans+=(dy-y+1)*2-(y==0);//只需要考虑一半 但要特别考虑y==0的情况
}
printf("%lld\n",ans);
}
return 0;
}
Codeforces Round 940 (Div. 2) and CodeCraft-23
虽然已经pupil了但是还是继续vp 备战省赛喵
怎么全是异或之类的 我是真的不会啊QwQ
A. Stickogon
组正多边形而不是正方形 直接全部发配去组三角形就行了 多出来的丢掉(或者理解为加进去组正方形了)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int bol[150]={0};
for(int i=1;i<=n;i++)
{
int tmp;
scanf("%d",&tmp);
bol[tmp]++;
}
int ans=0;
for(int i=1;i<=100;i++)
{
ans+=bol[i]/3;
}
printf("%d\n",ans);
}
return 0;
}
C. How Does the Rook Move?
只要放了一个棋他所在行和列都不能放了 而且不在对角线的话对应位置还会多放一个 其实就相当于每次删掉了两行两列的选择空间 放在对角线则是删掉了一行一列的选择空间 所以a和b可以看做把n减小了 然后n有一个递推关系 预处理就行
经过上面的分析 我们每放一颗棋子可能造成的影响 所以对于之后的每一次下棋的可能性f(i) 如果放在对角线上则是有f(i-1)种情况 否则则是f(i-2)*f(i-1)*2 所以公式就是
预处理f[300001]数组就可以了 记得取模
#include <bits/stdc++.h>
#define int long long
#define MOD 1000000007
using namespace std;
int res[300010]={0};
void Initialization()
{
res[0]=1;
res[1]=1;
for(int i=2;i<=300000;i++)
{
res[i]=(res[i-1]%MOD+2*(i-1)*res[i-2]%MOD)%MOD;
}
}
signed main()
{
int T=1;
scanf("%lld",&T);
Initialization();
while(T--)
{
int n,k;
scanf("%lld%lld",&n,&k);
while(k--)
{
int a,b;
scanf("%lld%lld",&a,&b);
if(a==b) n--;
else n-=2;
}
printf("%lld\n",res[n]);
}
return 0;
}
/*
Thought of calling ya
But you won't pick up
Another fortnight lost in America
Move to Florida
Buy the car you want
But it won't start up
Til I touch, touch, touch you
*/
B. A BIT of a Construction
异或是真的不会 先写完C题啃了半天才写出来
构造1最多 所以尽量全是0嘛 数字越多肯定1越少 然后第一个数让他全是1 第二个数拿k减一下就行了
#include <bits/stdc++.h>
using namespace std;
/*
One kiss is all it takes
Falling in love with me
Possibilities, I look like all you need
*/
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
if(n==1)
printf("%d\n",k);
else
{
int i=2;
while(i<=k+1)
{
i*=2;
}
i/=2;
printf("%d %d ",i-1,k+1-i);
for(int i=3;i<=n;i++)
printf("0 ");
printf("\n");
}
}
return 0;
}
【LGR-184-Div.3】洛谷基础赛 #11 &「MYOI」Round 3
脑子转不过来 写了一题半 洛谷的题就不补了
「MYOI-R3」字符串
开个桶减一下就行了
#include <bits/stdc++.h>
using namespace std;
int main()
{
string a,b;
cin>>a>>b;
int al=a.length();
int bl=b.length();
int ab[150]={0},bb[150]={0};
for(int i=0;i<al;i++) ab[a[i]]++;
for(int i=0;i<bl;i++) bb[b[i]]++;
int ans=0;
for(int i='a';i<='z';i++)
{
if(ab[i]>=bb[i])
ans+=ab[i]-bb[i];
}
printf("%d\n",al-ans);
return 0;
}
「MYOI-R3」消消乐
剩下的两个数一定是最大的两个 删掉的数一定都是他们的因数 就算是他们因数的公因数也肯定还是他们的因数 所以直接找他们的因数 只要有不是他们因数的那肯定就No了 但是就算全是他们的因数应该还有别的情况要输出No来着 暂时还没想通 到这里是50分
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[n];
for(int i=0;i<n;i++) scanf("%d",&a[i]);
sort(a,a+n);
int x=a[n-1],y=a[n-2];
int flag=1;
for(int i=n-3;i>=0;i--)
{
if(x%a[i]!=0&&y%a[i]!=0)
{
flag=0;
break;
}
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
Codeforces Round 916 (Div. 3)
一眼顶真 鉴定为Div4 打得比较爽的一场
A. Problemsolving Log
开桶存 然后比较对应字母有没有到对应数字就行
#include <bits/stdc++.h>
using namespace std;
/*
Yeah, it's all eyes on me, and I'ma send it up to Pac, ayy
Put the wrong label on me, I'ma get 'em dropped, ayy
Sweet Chin Music and I won't pass the aux, ayy
How many stocks do I really have in stock? Ayy
One, two, three, four, five, plus five, ayy
*/
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
string s;
cin>>s;
int bol[150]={0};
for(int i=0;i<n;i++)
{
bol[s[i]]++;
}
int ans=0;
for(int i='A';i<='Z';i++)
{
if(bol[i]>i-'A')
ans++;
}
printf("%d\n",ans);
}
return 0;
}
B. Preparing for the Contest
正着数反着数 输出 下班
#include <bits/stdc++.h>
using namespace std;
/*
Falling, falling
螺旋状に堕ちてゆく摩天楼に
今 falling, falling
二人ぼっち気づかない
カーテンコールにも
どこまでも
この身任せて
いつの間に傷が埋まってく yeah
*/
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=n-k; i<=n; i++)
{
printf("%d ",i);
}
for(int i=n-k-1; i>=1; i--)
{
printf("%d ",i);
}
printf("\n");
}
return 0;
}
C. Quests
不需要考虑顺序 遍历最远做到第i个任务 然后维护a的前缀和和b的最大值就行
#include <bits/stdc++.h>
using namespace std;
/*
よふかしのうた
照らしてって moonlight
目を奪ってブルーライト
ネオンサインが呼ぶ表裏
よふかしのうた
連れ去って midnight
血走った red eyes
大人達の子守唄
*/
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n,k;
scanf("%d%d",&n,&k);
int suma[n+1]={0},maxb[n+1]={0};
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
suma[i]=suma[i-1]+a;
}
for(int i=1;i<=n;i++)
{
int b;
scanf("%d",&b);
maxb[i]=max(maxb[i-1],b);
}
int ans=0;
for(int i=1;i<=min(n,k);i++)
{
ans=max(ans,suma[i]+(k-i)*maxb[i]);
}
printf("%d\n",ans);
}
return 0;
}
D. Three Activities
无脑选最大是不可以的 因为可能两个数组的最大值出现在同一个位置 三层遍历 每次遍历最大的3个数就好
#include <bits/stdc++.h>
using namespace std;
struct point
{
int data;
int pos;
};
bool cmp(point a,point b)
{
return a.data>b.data;
}
/*
All my life
They been tryin' to keep me down
All this time
Never thought I would make it out
They couldn't break me, they couldn't break me
They couldn't take me, they couldn't take me
All my life
They been tryin' to keep me down
*/
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
point a[n],b[n],c[n];
for(int i=0;i<n;i++)
{
scanf("%d",&a[i].data);
a[i].pos=i;
}
for(int i=0;i<n;i++)
{
scanf("%d",&b[i].data);
b[i].pos=i;
}
for(int i=0;i<n;i++)
{
scanf("%d",&c[i].data);
c[i].pos=i;
}
sort(a,a+n,cmp);
sort(b,b+n,cmp);
sort(c,c+n,cmp);
/*for(int i=0;i<n;i++)
{
printf("%d ",a[i].data);
}*/
int ans=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
if(a[i].pos==b[j].pos||a[i].pos==c[k].pos||b[j].pos==c[k].pos)
{
continue;
}
else
{
ans=max(ans,a[i].data+b[j].data+c[k].data);
}
}
}
}
printf("%d\n",ans);
}
return 0;
}
E. Game with Marbles
这题不开龙龙样例都过不了了就不多说了
变了0之后就废了不会出现二次操作 也就是其实是对所有数扫一遍 对两个人来说都尽量找a[i]+b[i]最大的位置是最优选择 所以维护一个对应位置和的结构体数组排序就行
#include <bits/stdc++.h>
#define int long long
using namespace std;
struct point
{
int data;
int pos;
};
bool cmp(point a,point b)
{
return a.data>b.data;
}
/*
I made you think that I would always stay
I said some things that I should never say
Yeah, I broke your heart like someone did to mine
And now you won't love me for a second time
*/
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int n;
scanf("%lld",&n);
int a[n],b[n];
point c[n];
for(int i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=0;i<n;i++)
{
scanf("%lld",&b[i]);
c[i].data=a[i]+b[i];
c[i].pos=i;
}
sort(c,c+n,cmp);
int ans=0;
for(int i=0;i<n;i++)
{
if(i%2==0)//Alice先动手(偶数)
{
ans+=a[c[i].pos]-1;
}
else//Bob后动手(奇数)
{
ans-=b[c[i].pos]-1;
}
}
printf("%lld\n",ans);
}
return 0;
}
Codeforces Round 913 (Div. 3)
打的比较难受的一把 补题含量比较多
(算了不加歌词了感觉跟风没啥意思)
A. Rook
签到题出师不利 scanf输入逻辑搞乱了浪费了几分钟
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
char ch;
int d;
string s;
cin>>s;
ch=s[0];
d=s[1]-'0';
for(int i=1;i<=8;i++)
{
if(i==d)
continue;
printf("%c%d\n",ch,i);
}
for(char i='a';i<='h';i++)
{
if(i==ch)
continue;
printf("%c%d\n",i,d);
}
}
return 0;
}
B. YetnotherrokenKeoard
维护两个栈存储上次大写和小写字母出现的下标
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
string s;
cin>>s;
int l=s.length();
stack<int>a,A;
for(int i=0; i<l; i++)
{
if(s[i]=='b')
{
if(!a.empty())
{
s[a.top()]=0;
a.pop();
}
s[i]=0;
}
else if(s[i]=='B')
{
if(!A.empty())
{
s[A.top()]=0;
A.pop();
}
s[i]=0;
}
else if(islower(s[i]))
{
a.push(i);
}
else if(isupper(s[i]))
{
A.push(i);
}
}
for(int i=0; i<l; i++)
{
if(s[i]==0)
continue;
printf("%c",s[i]);
}
printf("\n");
}
return 0;
}
C. Removal of Unattractive Pairs
其实最后发现根本不需要考虑顺序之类的 那就开个桶就可以了 看最多的有没有超过一半 字符串长度为奇数的时候注意要特判就可以了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
string s;
cin>>s;
int bol[200]={0};
int m=-1;
for(int i=0;i<n;i++)
{
bol[s[i]-'0']++;
m=max(m,bol[s[i]-'0']);
}
//if(m>n/2)
//{
// printf("%d\n",m*2-n);
//}
printf("%d\n",max((n&1),m*2-n));
}
return 0;
}
D. Jumping Through Segments
二分没学好不会写 这是补题 二分好题
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n;
int l[200010],r[200010];
bool check(int k)
{
int a=0,b=0;
for(int i=0;i<n;i++)
{
a=max(a-k,l[i]);
b=min(b+k,r[i]);
if(a>b)
return false;
}
return true;
}
signed main()
{
int T=1;
scanf("%lld",&T);
while(T--)
{
int n;
scanf("%lld",&n);
for(int i=0;i<n;i++)
{
scanf("%lld%lld",&l[i],&r[i]);
}
int left=-1,right=1e9;
while(right>left+1)
{
int nxt=(left+right)/2;
if(check(nxt))
right=nxt-1;
else
left=nxt+1;
}
printf("%lld\n",right);
}
return 0;
}
Codeforces Round 939 (Div. 2)
本文最后一场vp 上月刊堂堂完结!
A. Nene's Game
没问你剩谁 问你剩几个那可太好办了 只要减到小于最小的a就行了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int k,q,a=1e9;
int m=1e9;
int n;
scanf("%d%d",&k,&q);
for(int i=1; i<=k; i++)
{
scanf("%d",&a);
m=min(m,a);
}
for(int i=1; i<=q; i++)
{
scanf("%d",&n);
printf("%d ",min(m-1,n));
}
printf("\n");
}
return 0;
}
B. Nene and the Card Game
其实这个游戏先手是绝对劣势的 只要是一人一张的牌先手出了之后后手再出就行了 所以先手能保证自己能拿到的分只有两张牌都在自己手上的情况 而对面既然足够聪明就自然不会把局势翻转 因为两个人对子的个数一定相同所以对方只要在你出对子的时候也出对子就行
所以答案就是开个桶存有多少对子
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[n+1]={0};
for(int i=0;i<n;i++)
{
int cc;
scanf("%d",&cc);
a[cc]++;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]==2)
ans++;
}
printf("%d\n",ans);
}
return 0;
}
C. Nene's Magical Matrix
不难看出我想要的是下面这样的序列才能使总和最大
1 2 3 4 5
2 2 3 4 5
3 3 3 4 5
4 4 4 4 5
5 5 5 5 5
那么现在的问题就是如何构造 如果正序的填的话势必会出现小数覆盖大数的问题 但是反过来就没有这个问题 先把右下角的5安排上 其他先不管 在考虑倒数2*2的位置 以此类推
每次都填1~n就行(我一开始题意甚至就理解成只能填1~n)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int a[n+1]={0};
for(int i=0;i<n;i++)
{
int cc;
scanf("%d",&cc);
a[cc]++;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]==2)
ans++;
}
printf("%d\n",ans);
}
return 0;
}
写在最后
好充实的半个月 打了好多场vp 然后想冲回的pupil也冲回来了(虽然好像还是没学什么新算法)希望gdcpc和蓝桥杯国赛有狗运保佑喵