D - Card collection
送温暖的签到题,裸的最短路。点数很少,只要Floyd就可以
E - Base Station Sites
签到题,最大值最小明显是二分问题,直接二分最终的位置,每次判断一下能不能放完就行
G - Optimal Coin Change
比较简单的dp,首先我们利用完全背包,维护一个最少的使用硬币的个数,在此基础上,我们维护一个答案数组c[i][j] 代表钱数为i的时候,第j种硬币最少i的使用个数,每次转移的时候我们将答案向新的答案更新
#include
#include
#define ll long long
using namespace std;
#define INF 0x3f3f3f3f
int a[20];
int dp[2010];
int c[2010][20];
int main()
{
//freopen("input.txt","r",stdin);
int n,v;
while(~scanf("%d%d",&v,&n))
{
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
memset(dp,INF,sizeof(dp));
memset(c,0,sizeof(c));
dp[0]=0;
for(int i=1;i<=n;++i)
for(int j=0;j<=v;++j)
if(j+a[i]<=v)
{
if(dp[j+a[i]]>=dp[j]+1)
{
dp[j+a[i]]=dp[j]+1;
// dp[i][i]++;
for(int k=1;k<=n;++k)
{
c[j+a[i]][k]=c[j][k];
}
c[j+a[i]][i]++;
}
// dp[j+a[i]]=min(dp[j]+1,dp[j+a[i]]);
}
if(dp[v]==INF)
puts("-1");
else
{
for(int i=1;i<n;++i)
printf("%d ",c[v][i]);
printf("%d\n",c[v][n]);
}
}
return 0;
}
F - Nearby Bicycles
水题,直接暴力就行,最好不要用sqrt,直接longlong不开方判断就行
I - Count the Even Integers
java大数+找规律。首先我们不用将杨辉三角全部打出来,只要将奇偶表示成01,然后按照异或规则打个表,会发现打出来一个很漂亮的图形。其中大三角和小三角互相组合,我们预处理小的三角的答案个数,然后递归一下去计算
import java.lang.*;
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static BigInteger a[] = new BigInteger[201];
static BigInteger p[] = new BigInteger[201];
static BigInteger TWO = new BigInteger("2");
static BigInteger TRI = new BigInteger("3");
public static BigInteger fun(BigInteger n)
{
int x = 0;
for(int i = 0;i<201;i++)
{
if(n.compareTo(p[i]) < 0)
{
x = i-1;break;
}
}
//System.out.print(x);
BigInteger t = n.subtract(p[x]);
if(t.compareTo(BigInteger.ZERO) == 0) return a[x];
BigInteger res = t.multiply(p[x].add(p[x]).subtract(BigInteger.ONE).subtract(t)).divide(TWO);
return a[x].add(fun(t).multiply(TWO)).add(res);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
p[0] = BigInteger.ONE;
for(int i = 1;i<200;i++)
{
p[i] = p[i-1].multiply(TWO);
}
a[0] = a[1] = BigInteger.ZERO;
for(int i = 2;i<200;i++)
{
BigInteger t = p[i-1].multiply(p[i-1].subtract(BigInteger.ONE)).divide(TWO);
a[i] = a[i-1].multiply(TRI).add(t);
}
Scanner sc = new Scanner(System.in);
BigInteger n;
while(sc.hasNext())
{
n = sc.nextBigInteger();
System.out.println(fun(n.add(BigInteger.ONE)));
}
}
}
B - Black and White
是一个线段树求矩形交的改一改做法,我们记个标记代表这个点有没有被反转。反转了一定要将区间值同时反转
#include
#define ll long long
#define pr pair
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define next fuck
using namespace std;
const int MAXN = 1e5 + 5;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,ls
#define rson mid+1,r,rs
int cnt[MAXN],sum[MAXN],len[MAXN];
struct Seg
{
int l,r,h,d;
Seg(){
}
Seg(int _l,int _r,int _h,int _d) {
l = _l,r = _r,h = _h,d = _d;}
bool operator < (const Seg &rhs) const
{
return h < rhs.h;
}
}a[MAXN];
void update_rev(int rt)
{
cnt[rt] ^= 1;
sum[rt] = len[rt] - sum[rt];
}
void push_down(int rt)
{
if(cnt[rt])
{
update_rev(ls);
update_rev(rs);
cnt[rt] = 0;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L <=l && r <= R)
{
update_rev(rt);
return ;
}
push_down(rt);
int mid = (l + r) >> 1;
if(L <= mid) update(L,R,c,lson);
if(R > mid) update(L,R,c,rson);
sum[rt] = sum[ls] + sum[rs];
}
void build(int l,int r,int rt)
{
cnt[rt] = sum[rt] = 0;
len[rt] = r - l + 1;
if(l == r) return ;
int mid =(l + r)>> 1;
build(lson);
build(rson);
}
int n,k;
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
scanf("%d%d",&n,&k);
int tot = 0;
for(int i = 1;i<=k;i++)
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&x2,&y1,&y2);
a[tot++] = Seg(x1,x2,y1,1);
if(y2 < n) a[tot++] = Seg(x1,x2,y2+1,-1);
}
sort(a,a+tot);
build(1,n,1);
int ans = 0;
for(int i = 1,j = 0;i<=n;i++)
{
while(j < tot && a[j].h == i)
{
update(a[j].l,a[j].r,1,1,n,1);
j++;
}
ans += sum[1];
}
printf("%d\n",ans);
}
return 0;
}
A - Fermat’s Optimization Problem
给出n,z,求 f ( x , y , z ) = ∣ x n − y n − z n ∣ f(x,y,z) = |x^n-y^n-z^n| f(x,y,z)=∣xn−yn−zn∣最小值。
感觉可以随机搞一发,但是发现n最大只有10,我们先预处理一下pow(JAVA大数的pow慢的绝望),然后枚举Y,用二分求出来当前Y下最小的X值,注意特判一下1的情况
import java.util.*;
import java.math.BigInteger;
public class Main
{
static BigInteger pow[][] = new BigInteger[100005][12];
public static void main(String[]args)
{
for(int i = 1;i<=100000;i++)
{
pow[i][0] = BigInteger.ONE;
for(int j = 1;j<=10;j++)
{
pow[i][j] = pow[i][j-1].multiply(BigInteger.valueOf((long)i));
}
}
String INF = "1";
for(int i =1;i<=60;i++) INF = INF+"0";
Scanner sc = new Scanner(System.in);
int ca = sc.nextInt();
while(ca-- != 0)
{
int n = sc.nextInt(),z = sc.nextInt();
int X = 0,Y = 0;
BigInteger ans = new BigInteger(INF);
for(int i = 2;i<z;i++)
{
BigInteger num = pow[1][n].add(pow[i][n]).subtract(pow[z][n]);
if(num.compareTo(BigInteger.ZERO) >= 0)
{
if(num.compareTo(ans) == -1) {
ans = num;
X = 1;
Y = i;
//System.out.println(X+" "+Y+" "+num);
}
continue;
}
int l = 1,r = i-1;
while(l < r)
{
int mid = (l+r+1>> 1);
num = pow[mid][n].add(pow[i][n]).subtract(pow[z][n]);
if(num.compareTo(BigInteger.ZERO) == -1)
{
l = mid;
}
else r = mid-1;
}
num = pow[l][n].add(pow[i][n]).subtract(pow[z][n]);
num = num.multiply(BigInteger.valueOf(-1l));
if(num.compareTo(ans) == -1)
{
ans = num;
X = l;
Y = i;
}
if(l < i-1)
{
l++;
num = pow[l][n].add(pow[i][n]).subtract(pow[z][n]);
if(num.compareTo(ans) == -1)
{
ans = num;
X = l;
Y = i;
}
}
//System.out.println(X+" "+Y+" "+num);
}
System.out.printf("%d %d ",X,Y);
System.out.println(ans);
}
sc.close();
}
}