加油加油加油!
思路:这题数据范围2e5,如果想暴力的话,会果断超时这毋庸置疑,正解应该是贪心,对于怎样选择使用技能,选择方法:当剩余怪物的个数大于或等于x时,我们选择AOC伤害,如果小于,也就是说还不如我一滴血一滴血的去打怪物划算,就选择单体伤害了。
我们可以通过排序解决这个问题,找出使用多少次AOE伤害后剩下x个怪物,之后把这x个怪物的血量加起来即可。
要有特判一次也不使用AOE伤害的情况
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 300010;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
ll a[maxn];
int main()
{
ll n,x;
ll ans=0;
ll cnt=0;
cin>>n>>x;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
cnt+=a[i];
}
sort(a+1,a+n+1);
if(n-x+1<=0){
cout<<cnt<<endl;
return 0;
}
ans=a[n-x+1]*x;
for(int i=n-x+1;i<=n;i++){
ans+=a[i]-a[n-x+1];
}
cout<<ans<<endl;
return 0;
}
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
ll pre[maxn];
ll power(ll a,ll b,ll c) {
ll ans=1;
a = a%c;
while(b) {
if(b&1)
ans=ans*a%c;
a=a*a%c;
b=b>>1;
}
return ans;
}
ll c(ll a, ll b) {
if (b>a) return 0;
ll ans=pre[a]*power(pre[b]*pre[a-b]%mod,mod-2,mod)%mod;
return ans;
}
void init() {
pre[0]=1;
for (int i=1;i<maxn;i++)
pre[i]=pre[i-1]*i%mod;
}
int main() {
init();
ll n,m,k;
cin >>n>>m>>k;
if (n<m) swap(n,m);
if (k==1||k>n+m)
cout<<0<<endl;
else{
ll ans=0;
for (int i=1;i<=n;i++) {
int j=k-i;
if (j<=0) continue;
ll x=c(n-1,i-1),y=c(m-1,j-1);
if (j==i-1||j==i+1) {
ans=(ans+x%mod*y%mod)%mod;
}
else if (j==i){
ans=(ans+2*x%mod*y%mod)%mod;
}
}
cout<<ans<<endl;
}
return 0;
}
题解:这个题我们可以先通过并查集把联通的白块给合并起来,并且实时更新一个区域白块数量的最大值(只记录在根节点位置),然后我们在找出黑块的位置,并且查找他周围白块的数量(数量不要忘记加上当前黑块的数量,也就是1),因为一个区域的白块最大值只记录在父节点的位置上,所以我们需要找到父节点的位置再加数量
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 2e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
char s[maxn];
vector <vector<int> >maps;
int a[maxn],f[maxn];
int ifind(int x){
if(f[x]==x) return x;
return f[x]=ifind(f[x]);
}
void mer(int x,int y){
int dx=ifind(x);
int dy=ifind(y);
if(dx!=dy){
f[dx]=dy;
a[dy]+=a[dx];
}
}
int main()
{
int n;
cin>>n;
scanf("%s",s+1);
maps.resize(maxn);
for(int i=0;i<maxn;i++) f[i]=i,a[i]=1;
for(int i=0;i<n-1;i++){
int x,y;
scanf("%d%d",&x,&y);
maps[x].push_back(y);
maps[y].push_back(x);
if(s[x]=='W'&&s[y]=='W'){
mer(x,y);
} //
}
int imax=0;
for(int i=1;i<=n;i++){
if(s[i]=='W') imax=max(imax,a[ifind(i)]);
}
for(int i=1;i<=n;i++){
int ans=1;
if(s[i]=='B'){
for(int j=0;j<maps[i].size();j++)
if(s[maps[i][j]]=='W') ans+=a[ifind(maps[i][j])];
imax=max(imax,ans);
}
}
cout<<imax<<endl;
return 0;
}
QAQ这个题主要考察的知识点是逆元的知识点(虽然之前做过逆元的题目,但是这次完全没想到用这个方法,甚至自己傻乎乎的在想最大公约数)
题解:这个题主要考的逆元的知识,它可以把分数当成整数来进行运算,这个题我们可以先求出怎么抽也抽不中的概率,然后用一减去这个概率即可。
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 1e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
ll a[maxn],b[maxn];
ll qp(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
ll ans=1;
for(int i=0;i<n;i++){
ans=ans*(a[i]-b[i])%mod*qp(a[i],mod-2)%mod;
}
ans=(mod+(1-ans))%mod;
cout<<ans<<endl;
return 0;
}
题解:这个题主要是考察了栈的运用,可以用数组模拟一下栈。
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 300010;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
char str[maxn],ans[maxn];
int main()
{
int i,len,j;
scanf("%s",str);
len=strlen(str);
ans[0]=str[0];
j=1;
for(i=1;i<len;i++)
{
ans[j]=str[i]; //进栈
if(j>=1&&ans[j]==ans[j-1]) //出栈
j-=2;
j++;
}
ans[j]='\0';
if(j==0) printf("0");
else{
cout<<ans<<endl;
}
return 0;
}
题解:把已知的数全都加起来,再把未知的分别假设为1和5即可
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 300010;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
double x=0,t;
for(int i=0;i<n-m;i++){
scanf("%lf",&t);
x+=t;
}
double imax=(x+5*m)/n;
double imin=(x+m)/n;
printf("%.5f %.5f",imin,imax);
return 0;
}
题解:这个题方程其实是一个具有单调性的方程(我也不知道怎么证明,用了Mathematic画了一下这个图像,有了神奇的发现),所以二分就行,这里说误差小于1e-7所以二分的精确值我直接设到了1e-8
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 1e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
double a,b,c;
bool che(double x){
if(pow(x,a)+b*log(x)>=c){
return true;
}
else return false;
}
int main()
{
cin>>a>>b>>c;
double l=0, r=1e9;
double mid;
double ans=0;
while(r-l>1e-8){
mid=(l+r)/2.0;
if(che(mid)){
ans=mid;
r=mid-1e-7;
}
else l=mid+1e-7;
}
printf("%.14f",ans);
return 0;
}
题解:用while不断输入,设置一个数组记录每个字母出现的次数
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 300010;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
string s;
int a[100];
int main()
{
while(cin>>s){
for(int i=0;i<s.size();i++){
a[s[i]-'a']++;
}
}
char x;
int imin=0;
for(int i=0;i<26;i++){
if(imin<a[i]){
imin=a[i];
x=i+'a';
}
}
cout<<x<<endl;
return 0;
}
题解:因为没有明确的给出m和n的范围,所以我们开一个一维数组当二维数组用就行,(即切分开)a[i*m+j]代表a[i][j]
然后预处理行和列最后相加即可
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 1e6+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
ll x[maxn];
ll hang[maxn];
ll lie[maxn];
ll a[maxn];
int main()
{
int n,m;
int cnt=1;
ll ans=0;
cin>>n>>m;
for(int i=1;i<=n*m;i++){
scanf("%lld",&x[i]);
ans+=x[i];
lie[i-(cnt-1)*m]+=x[i];
if(i%m==0){
hang[cnt++]=ans;
ans=0;
}
}
for(int i=1;i<=n;i++){
for(int f=1;f<=m;f++){
printf("%lld ",hang[i]+lie[f]-x[(i-1)*m+f]);
// cout<<"hang"<
// cout<<"lie"<
}
printf("\n");
}
return 0;
}
比赛的时候只想到可能会与二进制每个位0和1的个数有关,其他的确实没想到
题解:如果某位异或和为1 那只有两种情况
一种 1 1 1 另一种1 0 0
我们用高中所学过的组合公式即可
#pragma GCC optimize(3,"Ofast","inline")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 1e5+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1e9+7;
using namespace std;
ll a[100];
int main()
{
ll n,m;
cin>>n;
for(int i=0;i<n;i++){
scanf("%lld",&m);
for(int j=0;j<64;j++){
a[j]+=((m>>j)&1);
}
}
ll sum=0;
for(int i=0;i<64;i++){
sum+=(1ll<<i)%mod*(a[i]*(a[i]-1)*(a[i]-2)/6%mod)%mod;
sum+=(1ll<<i)%mod*(a[i]*(n-a[i])*(n-a[i]-1)/2%mod)%mod;
sum%=mod;
}
cout<<sum<<endl;
return 0;
}
萌新一枚,欢迎各位巨佬指出不足。