A Integer Moves
题意:略
题解:一共就三种情况,具体略(
需要注意的是sqrt()返回的并不是整型,记得前面加(Int)
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
#define sc scanf
#define pr printf
#define ll long long
#define mod 998244353
#define INT INT_MAX
ll dp[maxn][5];
int main() {
int t;
cin>>t;
while(t--){
int x,y;cin>>x>>y;
int k=(int)sqrt(x*x+y*y)*(int)sqrt(x*x+y*y);
//cout<<k<<"aaaa"<<(x*x+y*y)<<endl;
if(x==y&&x==0)cout<<0<<endl;
else if(k==(x*x+y*y))cout<<1<<endl;
else cout<<2<<endl;
}
return 0;
}
B XY Sequence
题意:略
题解:个人人为这个比A更清晰,模拟一下过程即可。能加则加,否则减。这样可尽最大可能加最多。
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
#define sc scanf
#define pr printf
#define ll long long
#define mod 998244353
#define INT INT_MAX
ll dp[maxn][5];
int main() {
int t;
cin>>t;
while(t--){
ll n,b,x,y;sc("%lld%lld%lld%lld",&n,&b,&x,&y);
ll sum=0;
ll now=0;
for(int i=0;i<n;i++)
{
if(now+x<=b)now+=1ll*x;
else now-=1ll*y;
sum+=now;
}
pr("%lld\n",sum);
}
return 0;
}
C Bracket Sequence Deletion
题意:两种方法消前缀,且题目说了the shortest prefix,即最短前缀。
而消前缀两种方法:
1.匹配 2.回文
题解:
这题乍一看立马想到括号匹配,仔细一想被带歪了
因为一共就几种情况:(我觉得括号很能迷惑人,改成字符就很恨很清楚)
1.( )可以消去——匹配
2.( ( 可以消去——aa
3. ) )可以消去——bb
4. )( 待定
)( 看作ba,可知无论中间的a有多少,找到一个b即可回文,即baaaaaab,如果没有,则不可能再消去了。
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
#define sc scanf
#define pr printf
#define ll long long
#define mod 998244353
#define INT INT_MAX
int main() {
int t;
cin>>t;
while(t--){
int n;sc("%d",&n);
string s;cin>>s;
int ans=0;int i;
for(i=0;i<s.size()-1;){
if(s[i]==')'&&s[i+1]=='('){
int c=i;
i+=2;
while(i<s.size()){
if(s[i]!=')') i++;
else break;
}
if(i<s.size()&&s[i]==')'){
ans++,i++;
}
else {
i=c;goto ans;
}
}
else {
ans++;
i+=2;
}
}
ans:pr("%d %d\n",ans,s.size()-i);
}
return 0;
}
D For Gamers. By Gamers.
题意:
士兵n,拥有金币C;
对n个士兵,每一个拥有花费:ci,伤害:di,生命hi。
怪物m;
对m个怪物,每一个拥有伤害:di,生命hi。
求,对m种怪物的最少金币杀死方案。
需注意:
1.Monocarp chooses one type of units
它每次只能选择一组士兵,可无限次重复消费ci
2.not once per second
不是论秒判断胜负,这里需要结合示例分析
题解:
可以看出:需满足
x为选择x次
(不用数学工具编了,直接看吧
存下dixhi-1的数组,然后二分查找满足题意的。
具体实现注意
一个数组di,hi
一个数组储存满足题意的dixhi-1
二分用到的数组,需要对第二个数组作处理:从前到后求前缀最大值
注意定义为ll会减少很多麻烦,不然多处都要特殊处理,容易遗忘。
#include<bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
using namespace std;
const ll maxn=1e6+10;
ll ci[maxn];
ll k[maxn];
int main()
{
int n,C;cin>>n>>C;
ll c,d,h;
for(int i=0;i<n;i++){
sc("%lld%lld%lld",&c,&d,&h);
ci[c]=max(ci[c],h*d);
}
for(int i=1;i<=C;i++)//+1????
for(int j=i;j<=C;j+=i)
k[j]=max(k[j],(j/i)*ci[i]-1);
for(int i=1;i<=C;i++)k[i]=max(k[i],k[i-1]);
int m;cin>>m;
while(m--){
sc("%lld%lld",&c,&h);
ll x=c*h;
int ans=lower_bound(k,k+C+1,x)-k;
if(ans>C)pr("-1\n");
else pr("%d ",ans);
}
pr("\n");
return 0;
}
【写在后面的碎碎念】
这题刚看到的时候,觉得有点像背包?但是因为注意1又否定。
n,m的范围是3e5,怎么莽怎么错,也想不到优化。
然后想,那会是每一组的值确定,例如dh相乘什么的?然后再二分?
但是应该是交叉的关系,怎么可能是这样。
遂放弃。
于是发现是自己数学不好()