A题.Berland Poker
读懂题意即可
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
ll t,n,m,k;
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld %lld",&n,&m,&k);
ll op=n/k;
if(m<=op)
{
printf("%lld\n",m);
continue;
}
else
{
ll ans=op;
m-=op;
ll u=k-1;
if(m%u==0)
{
printf("%lld\n",ans-m/u);
}
else
{
ans=ans-(m/u+1);
printf("%lld\n",ans);
}
}
}
return 0;
}
B题.New Theatre Square
只能选1 x 1 或 1 x 2的,如果1x1的价格的两倍小于1x2的,那么就全部用1x1的,否则能用1x2的就用1x2的
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char s[105][10005];
int main()
{
ll t,n,m,k,x,y;
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld %lld %lld",&n,&m,&x,&y);
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
}
if(2*x<=y)
{
ll cnt=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j]=='.')
{
cnt++;}
}
}
printf("%lld\n",cnt*x);
}
else
{
ll sx=0,sy=0;
for(int i=0;i<n;i++)
{
int j=0;
while(j<m)
{
if(j<m-1)
{
if(s[i][j]=='.'&&s[i][j+1]=='.')
{
sy++;j+=2;continue;}
if(s[i][j]=='.'&&s[i][j+1]!='.')
{
sx++;j++;continue;}
j++;
}
else
{
if(s[i][j]=='.')
{
sx++;j++;continue;}
j++;
}
}
}
printf("%lld\n",sx*x+sy*y);
}
}
return 0;
}
C题.Mixing Water
题意:有两种水,一种热水温度为h,一种凉水温度为c,只能按照一杯热水、一杯凉水、一杯热水、一杯凉水······的顺序添加到同一个桶中,问最少需添加几次,使得桶中水的平均温度最接近t
思路:因为精度问题WA了两次很难受,这题推一个式子即可,当添加次数为偶数时,桶内温度一定为(h+c)/2
设当添加次数为j,且j为奇数时,可得到这样一个式子:(((j-1)/2)*(h+c)+h)/j=t
这样可以把 j 解出来,j可能是个浮点数,只是个模糊数值吧,把j附近的整数枚举一遍求出最终的答案
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char s[105][10005];
int main()
{
ll t,h,c,f;
scanf("%lld",&t);
while(t--)
{
scanf("%lld %lld %lld",&h,&c,&f);
if(h<=f)
{
printf("1\n");
continue;}
double hh=h*1.0;
double cc=c*1.0;
double ff=f*1.0;
//double all=0;
double op=(hh+cc)/2.0;
if(ff<=op)
{
printf("2\n");continue;}
double ans=(hh-cc)/(ff*2.0-hh-cc);
double opc=ff-op;
ll df=ans;
ll pos;
double minn=99999999.0;
for(ll i=df-3;i<=df+3;i++)
{
if(i<=0){
continue;}
if(i%2==0)
{
double uu=ff-op;
if(uu<=minn)
{
pos=i;minn=uu;}
}
else
{
double ee=(((i-1)/2)*(h+c)*1.0+h*1.0)/(i*1.0);
double uu=fabs(ee-ff);
if(uu<minn)
{
pos=i;
minn=uu;
}
}
}
if(pos%2==0)
{
printf("2\n");}
else
{
printf("%lld\n",pos);}
}
return 0;
}
待更新·································先打lol去了
D题.Yet Another Yet Another Task
又是最后剩下半个小时,写了个假DP WA了好几次,唉。。。。
题意:求一段区间,使该区间去掉一个最大值后的区间和值最大,问区间和最大值是多少
思路:因为ai<=30,直接从0到30枚举最大值,对每次最大值求最大子段和
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[200005],d[200005];
int main()
{
ll n;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);}
ll ans=-9999999999999;
for(int i=0;i<=30;i++)
{
ll maxx=-9999999999999;
for(int j=1;j<=n;j++)
{
if(a[j]>i)
{
d[j]=0;}
else
{
d[j]=max(d[j-1]+a[j],(ll)0);
maxx=max(maxx,d[j]);}
}
ans=max(ans,maxx-i);
}
printf("%lld\n",ans);
return 0;
}
E题.Modular Stability
题意:给你一个n和k,要求在1~n内取k个数,对于任何正数x,x%这k个数任何排列方式后的值相同,问有多少种取法
思路:仿照样例1打个表,差不多就知道是咋回事了
再用组合数和逆元求出最终结果
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll mod=998244353,bb=1;
void init(ll r)
{
for(ll i=r;i>=1;i--)
{
bb=bb*i%mod;}
}
ll apow(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
{
s=s*a%mod;}
a=a*a%mod;
b>>=1;
}
return s%mod;
}
ll C(ll n,ll r)
{
ll aa=1;
//cout<<n<<" "<<r<<endl;
for(ll i=n;i>=n-r+1;i--)
{
aa=aa*i%mod;}
return aa*apow(bb,mod-2)%mod;
}
int main()
{
ll n,k;
cin>>n>>k;
if(n==k){
cout<<"1"<<endl;return 0;}
if(n<k){
cout<<"0"<<endl;return 0;}
if(k==1){
cout<<n<<endl;return 0;}
init(k-1);
ll ans=0;
for(ll i=1;i<=n;i++)
{
if(i+k>n)
{
break;}
ll maxx=n/i;
if(maxx<k){
continue;}
ans=(ans%mod+C(maxx-1,k-1)%mod)%mod;
}
cout<<ans<<endl;
return 0;
}