题目链接
B - Multiplication 2
做法:题目很简单,但是各种姿势不给A就很恶心,__int128 wa,ull 也wa,最后用java大数才A,服了。
看了别人的代码发现,用了一种 判断爆long long 的方法 ,具体看代码吧。
c++代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll solve() {
ll N, a;
cin >> N;
vector<ll> A(N);
for ( int i = 0; i < N; i++ ) {
cin >> A[i];
if ( A[i] == 0 ) return 0;//?????没输入完就返回了?
}
ll mx = 1e18;
ll m = 1, p = 1;
for ( int i = 0; i < N; i++ ) {
m *= A[i];
if ( m < p || m > mx ) return -1;//比之前的小了,就是爆longlong了
p = m;
}
return m;
}
int main() {
auto ans = solve();
cout << ans << "\n";
return 0;
}
Java代码:
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
BigInteger N=new BigInteger("1000000000000000000");
BigInteger ans=new BigInteger("1");
BigInteger n0=new BigInteger("0");
int flag=1;
int num=1;
for(int i=1;i<=n;++i){
BigInteger x=sc.nextBigInteger();
if(x.compareTo(n0)==0) num=0;
if(flag==0) continue;
ans=ans.multiply(x);
if(ans.compareTo(N)>0) {
flag=0;
}
}
if(num==0) System.out.println(0);
else if(ans.compareTo(N)>0||flag==0) System.out.println("-1");
else System.out.println(ans);
}
}
C - Multiplication 3
被这两题给恶心到了,-0.5 wa round 也wa,最后用java 的ROUND_DOWN过的。。
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
BigDecimal a,b;
a=sc.nextBigDecimal();
b=sc.nextBigDecimal();
BigDecimal ans=a.multiply(b);
System.out.println(ans.setScale(0, BigDecimal.ROUND_DOWN));
}
}
D - Div Game
唯一分解一下就好了。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline ll read()
{
ll x=0,w=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
return w==1?x:-x;
}
int main()
{
ll n=read();
int ans=0;
for(ll i=2;i*i<=n;++i){
if(n%i==0){
int num=0;
while(n%i==0) num++,n=n/i;
int l=1,r=1000,t=0;
//printf("i:%lld num:%d\n",i,num);
while(l<=r){
int mid=l+r>>1;
int res=mid*(mid+1)/2;
if(res>num) r=mid-1;
else t=mid,l=mid+1;
}
//printf("t:%d\n",t);
ans+=t;
}
}
if(n!=1) ans++;
printf("%d\n",ans);
}
E - Count Median
题意:给你n个区间[li,ri] n个数a[i]分别从n个区间内选一个,问形成的序列不同中位数的个数是多少
题解思路来自b站大佬:链接
做法:感觉这类题型见过不下四遍了,而且不同题还有不同的解法,要么是列公式 连续区间求导还是求和(牛客某次练习赛最后一题),要么就是跟这题一样,数学分析分析
(ccpc wannfly 训练营重现赛某题:期望逆序数)
还有一个忘记在哪个地方了。
这题的思路大概就是
对于一个 x 能否成为中位数,判断他的充要条件是什么。
视频里说了结论:
对于n是奇数来说,
1、右端点 小于x的 区间 个数不超过n/2+1个,
2、左端点 大于x的 区间 个数不超过n-(n/2)=n/2+1
对于n是偶数
1、用上面的方法会找到两个合法的区间
[a1,b1] [a2,b2] 由于n数的中位数是 中间两个数之和/2 所以这里的合法区间就是 b1+b2-(a1+a2)+1
那么如何求这些个x呢?对左端点集a排个序,中间的数就是满足充要条件的,右端点集b 也类似
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
long long a[200010], b[200010];
int n;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
}
sort(a + 1, a + n + 1);
sort(b + 1, b + n + 1);
if (n % 2) {
//printf("b:%lld a:%lld\n",b[n/2+1],a[n/2+1]);
cout << b[n / 2 + 1] - a[n / 2 + 1] + 1;
} else {
cout << b[n / 2] + b[n / 2 + 1] - a[n / 2] - a[n / 2 + 1] + 1;
}
return 0;
}
/*
7
1 3
2 4
5 8
6 9
7 10
12 14
13 15
*/
F - Knapsack for All Subsets
做法:不考虑子集的话就是很水的dp 设dp[i][j]为前i项子集和为j的方案数。
转移方程:
for(int j=s;j>=a[i];--j){ add(dp[i][j],dp[i-1][j-a[i]]); }
然而这题是求所有子集的 再求上面的问题。
其实也很简单。 设dp[i][j]为前i项子集和为j的方案数。 每次新增i dp[i][j]=dp[i-1][j]*2.
为什么乘2呢,因为新增的a[i] 选 可以与前面的所有子集构成一次子集,若a[i]不选,就是继承前面的,那就是乘2了。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const ll mod=998244353;
inline ll read()
{
ll x=0,w=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
return w==1?x:-x;
}
const int N=3e3+10;
ll dp[N][N];
int a[N],n,s;
void add(ll &x,ll y)
{
x=(x+y)%mod;
}
int main()
{
n=read(),s=read();
rep(i,1,n) a[i]=read();
dp[0][0]=1;
rep(i,1,n)
{
for(int j=0;j<=s;++j) dp[i][j]=dp[i-1][j]*2%mod;
for(int j=s;j>=a[i];--j){
add(dp[i][j],dp[i-1][j-a[i]]);
}
}
printf("%lld\n",dp[n][s]);
}