1. 程式人生 > >2018年全國多校算法寒假訓練營練習比賽(第三場)題解

2018年全國多校算法寒假訓練營練習比賽(第三場)題解

排序 esp 註意 test sca big %d question long long

【題目連接】

由於在比賽期間發現了很多是原題,所以直接抄了原題代碼,稍後準備重寫。

A - 不凡的夫夫

答案為$\left\lfloor {\sum\limits_{i = 1}^n {{{\log }_8}i} } \right\rfloor + 1$,由於數據範圍的問題,可以將詢問離線,然後$1$到$10^7$跑一遍答案都在了

聽說有$O(1)$公式,表示並不會推...

#include <bits/stdc++.h>
using namespace std;

int ans[1000010];
struct Q {
  int n;
  int id;
  int ans;
}s[1000010];

double work(int x) {
  return log10(1.0 * x) / log10(8.0);
}

bool cmp(Q & a, Q & b) {
  return a.n < b.n;
}

int main() {
  int n;
  int T;
  cin >> T;
  for(int cas = 1; cas <= T; cas ++) {
    scanf("%d", &s[cas].n);
    s[cas].id = cas;
  }
  sort(s + 1, s + 1 + T, cmp);
  int now = 0;
  double A = 0.0;
  for(int i = 1; i <= T; i ++) {
    while(now < s[i].n) {
      now ++;
      A += work(now);
    }
    ans[s[i].id] = (int)A + 1;
  }
  for(int i = 1; i <= T; i ++) {
    printf("%d\n", ans[i]);
  }
  return 0;
}

B - 一個小問題

中國剩余定理,$n>20$無解,否則跑中國剩余定理

代碼稍後。

C - 守護白起

這題和POJ 2409一樣,只是數據範圍擴大了一下,註意取模。

代碼稍後。

D - 小牛vs小客

只有$1$和$2$小牛會贏,其余都是小客贏。

#include <bits/stdc++.h>
using namespace std;

int main() {
  int n;
  while(cin >> n) {
    if(n > 2) printf("XiaoKe\n");
    else printf("XiaoNiu\n");
  }
  return 0;
}

E - 進擊吧!階乘

大數運算,直接上了Java。

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

public class Main {
	static Scanner cin = new Scanner(System.in);
	
	public static void main(String[] args) {
		while(cin.hasNext()) {
			int n = cin.nextInt();
			BigInteger ans = BigInteger.ONE;
			for(int i = 1; i <= n; i ++) {
				ans = ans.multiply(BigInteger.valueOf(i));
			}
			System.out.println(ans);
		}
	}
}

F - 小牛再戰

這題我是看樣例猜的,除去1的數字全部異或起來,看是否為$0$。原因還要深入研究一下。

#include <bits/stdc++.h>
using namespace std;

int a[1000];
int n;

int main() {
  while(~scanf("%d", &n)) {
    if(n == 0) break;
    int ok = 0;
    for(int i = 1; i <= n; i ++) {
      scanf("%d", &a[i]);
      if(a[i] != 1) ok ^= a[i];
    }
    if(ok) printf("Win\n");
    else printf("Lose\n");
    
  }
  return 0;
}

G - 大水題

$狀壓dp$。

$dp[i]$表示 被$i$狀態的數字整除的數字有幾個,倒著減下來能算出能 只能 被被狀態$i$整除的數字有幾個,$dp[0]$就是答案。看一下代碼就能明白了。

#include <bits/stdc++.h>
using namespace std;

long long x[10];
long long st[1000];
long long dp[1000];

void init() {
  x[0] = 2;
  x[1] = 5;
  x[2] = 11;
  x[3] = 13;
  for(int j = 0; j < (1 << 4); j ++) {
    st[j] = 1;
    for(int p = 0; p < 4; p ++) {
      if(j & (1 <<p)) st[j] *= x[p];
    }
   // cout << j << " " << st[j] << endl;
  }
}

int main() {
  init();
  long long n;
  while(~scanf("%lld", &n)) {
    long long ans = 0;
    for(int i = 0; i <= 20; i ++) {
      dp[i] = 0;
    }
    for(int i = 0; i < 16; i ++) {
      dp[i] = n / st[i];
    }
    for(int i = 15; i >= 0; i --) {
      for(int j = i + 1; j <= 15; j ++) {
        if((i | j) == j) {
          dp[i] -= dp[j];
        }
      }
    }
    printf("%lld\n", dp[0]);
  }
  return 0;
}

H - 向左走

這題和POJ 1696一樣,每次極角度排序找第一個即可。

代碼稍後。

I - 三角形

皮克定理,這題和HDU 1705一樣。

代碼稍後。

2018年全國多校算法寒假訓練營練習比賽(第三場)題解