一个 2019 2019 2019的无向连通图,最少的边应该是 n − 1 n-1 n−1条,也就是 2018 2018 2018,构成一颗树。
12.5 M B 12.5MB 12.5MB中 1 M B = 2 20 B 1MB=2^{20}B 1MB=220B,所以也就是 12.5 ∗ 2 20 = 13107200 B 12.5*2^{20}=13107200B 12.5∗220=13107200B。
组合数学的一道题目,题目中只有两个 A A A是相等的总共 7 7 7个字符,我们先排 A A A是 C 7 2 C_{7}^{2} C72另外的是 A 5 5 A_{5}^{5} A55,所以答案是 C 7 2 ∗ A 5 5 = 2520 C_{7}^{2}*A_{5}^{5}=2520 C72∗A55=2520.
我后面用暴力验证了一下,以下是暴力的代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
map<string, bool> mp;
int main() {
int sum = 0;
int cnt[10] = {0};
string s = "LANQIAO";
for (int i = 0; i < 7; i++)
for (int j = 0; j < 7; j++)
for (int k = 0; k < 7; k++)
for (int l = 0; l < 7; l++)
for (int m = 0; m < 7; m++)
for (int n = 0; n < 7; n++)
for (int o = 0; o < 7; o++) {
memset(cnt, 0, sizeof(cnt));
cnt[i]++;
cnt[j]++;
cnt[k]++;
cnt[l]++;
cnt[m]++;
cnt[n]++;
cnt[o]++;
bool flag = false;
for (int ii = 0; ii < 7; ii++) {
if (cnt[ii] > 1) flag = true;
}
if (flag) continue;
//cout << s[1] <
string t = "";
t += s[i];
t += s[j];
t += s[k];
t += s[l];
t += s[m];
t += s[n];
t += s[o];
//cout << t << endl;
if (mp[t] == false) mp[t] = true, sum++;
}
cout << sum << endl;
}
直接暴力求出 8 8 8个括号的序列有 2 8 2^8 28中可能,所以枚举每种可能,再用栈去判断是否是合法序列。
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
int main() {
int n = 8, sum = 0;
for (int i = 0; i < (1 << n); i++) {
string s = "";
for (int j = 0; j < n; j++) {
if ((1 << j) & i) s += ')';
else s += '(';
}
//cout << s << endl;
stack<char> st;
for (int j = 0; j < s.size(); j++) {
if (st.empty()) st.push(s[j]);
else if (s[j] == ')' && st.top() == '(') {
st.pop();
} else st.push(s[j]);
}
if (st.size() == 0) {
cout << s << endl;
sum++;
}
}
cout << sum << endl;
}
用一个数组 c n t cnt cnt(0对应 a a a)去记录每一个对应的字母 + 3 +3 +3% 26 26 26最后的最后的值,然后遍历字符串,最后就有 c n t [ a [ i ] − ′ a ′ ] + ′ a ′ cnt[a[i]-'a']+'a' cnt[a[i]−′a′]+′a′。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
int main() {
char s[110];
int cnt[50] = {0};
for (int i = 0; i < 26; i++) {
cnt[i] = (i + 3) % 26;
}
scanf("%s", s);
int len = strlen(s);
for (int i = 0; i < len; i++) {
int x = cnt[s[i] - 'a'];
char c = x + 'a';
printf("%c", c);
}
return 0;
}
题目数据最后到 1 e 6 1e6 1e6,所以暴力就可以解决问题了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
int main() {
int n, a, b, c, sum = 0;
read(n);
read(a), read(b), read(c);
for (int i = 1; i <= n; i++) {
if (i % a != 0 && i % b != 0 && i % c != 0) sum++;
}
out(sum);
return 0;
}
用四个循环写出螺旋矩阵,一下是代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
int b[1010][1010];
int main() {
int n, m = 0, t = 0, hang, lie, x, y;
cin >> n >> m >> x >> y;
hang = m, lie = n;
int ci = lie / 2 + lie % 2;
n = n * m, m = 0;
for(int i = 0; i < ci; i++){
for(int j = i; j <= hang - i - 1 && m <= n - 1; j++)
b[i][j] = m++;
for(int j = i + 1; j <= lie - i - 2 && m <= n - 1; j++)
b[j][hang - i - 1] = m++;
for (int j = hang - i - 1; j >= i && m <= n - 1; j--)
b[lie - 1 - i][j] = m++;
for (int j = lie - 2 - i; j >= i + 1 && m <= n - 1; j--)
b[j][i] = m++;
}
out(b[x - 1][y - 1] + 1);
return 0;
}
如果使用 d f s dfs dfs的话,那么复杂度应该是 n m n^m nm,所以连 10 10 10都跑不过去,所以应该是用 d p dp dp解决了,我们可以设 d p i , j dp_{i,j} dpi,j为 i i i点中的大于\小于 j j j点,那么假如 i i i % 2 = = 0 2 == 0 2==0,这是个偶数点,那么 j j j点可行的方案有 d p i − 1. j + 1 + d p i , j − 1 dp_{i-1.j+1}+dp_{i,j-1} dpi−1.j+1+dpi,j−1,意思就是之前 i − 1 i-1 i−1时比 j j j打的点的数量加上 1 1 1~ j − 1 j-1 j−1的方案数,所以就有状态方程 d p i , j = { ( d p i − 1 , j + 1 + d p i , j − 1 ) % m o d i % 2==0 ( d p i − 1 , j − 1 + d p i , j + 1 ) % m o d i % 2==1 dp_{i,j}= \begin{cases} (dp_{i-1,j+1}+dp_{i,j-1})\% mod & \text{i \% 2==0} \\ (dp_{i-1,j-1}+dp_{i,j+1}) \% mod & \text{i \% 2==1} \end{cases} dpi,j={(dpi−1,j+1+dpi,j−1)%mod(dpi−1,j−1+dpi,j+1)%modi % 2==0i % 2==1
如果要省空间的话,可以使用滚动数组。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
const int maxn = 1010;
const int mod = 10000;
int dp[maxn][maxn] = {0};
int main() {
int m, n;
read(m), read(n);
for (int i = 1; i <= n; i++) dp[1][i] = n - i + 1;
for (int i = 2; i <= m; i++) {
if (!(i & 1)) {
for (int j = 1; j <= n; j++) dp[i][j] = (dp[i - 1][j + 1] + dp[i][j - 1]) % mod;
} else {
for (int j = n; j >= 1; j--) dp[i][j] = (dp[i - 1][j - 1] + dp[i][j + 1]) % mod;
}
}
if (m & 1) out(dp[m][1]);
else out(dp[m][n]);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
const int maxn = 1010;
const int mod = 10000;
int dp[2][maxn] = {0};
int main() {
int m, n, o = 1;
read(m), read(n);
for (int i = 1; i <= n; i++) dp[o][i] = n - i + 1;
o ^= 1;
for (int i = 2; i <= m; i++) {
if (!(i & 1)) {
for (int j = 1; j <= n; j++) dp[o][j] = (dp[o ^ 1][j + 1] + dp[o][j - 1]) % mod;
} else {
for (int j = n; j >= 1; j--) dp[o][j] = (dp[o ^ 1][j - 1] + dp[o][j + 1]) % mod;
}
o ^= 1;
}
if (m & 1) out(dp[o ^ 1][1]);
else out(dp[o ^ 1][n]);
return 0;
}
感觉是个最小生成树的问题,我们可以将所有的距离都求出来, n n n最大时 1000 1000 1000,所以最多的边的 100 0 2 1000^2 10002,这个范围用最小生成树时可行的,然后就是用 k r u s c a l kruscal kruscal写个模板,(需要注意的是距离的计算公式 h h h在括号外面)。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
const int maxn = 1e6 + 10;
struct Edge {
int u;
int v;
double dis;
bool friend operator < (Edge a, Edge b) {
return a.dis < b.dis;
}
};
Edge edge[maxn];
double pow2(double x) {return x * x;}
int father[maxn];
int FindFather(int x) {
int a = x;
while (father[x] != x) x = father[x];
while (a != father[a]) {
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void UnionFather(int a, int b) {
int fa = FindFather(a);
int fb = FindFather(b);
if (fa != fb) father[fa] = fb;
}
int main() {
int n;
double x[1010], y[1010], h[1010];
read(n);
for (int i = 1; i <= n; i++) {
read(x[i]), read(y[i]), read(h[i]);
}
int cnt = 0;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
edge[cnt].u = i;
edge[cnt].v = j;
edge[cnt++].dis = sqrt(pow2(x[i] - x[j]) + pow2(y[i] - y[j])) + pow2(h[i] - h[j]);
}
}
sort(edge, edge + cnt);
double ans = 0, ccnt;
for (int i = 0; i <= n; i++) father[i] = i;
for (int i = 0; i < cnt; i++) {
if (FindFather(edge[i].u) != FindFather(edge[i].v)) {
UnionFather(edge[i].u, edge[i].v);
ans += edge[i].dis;
ccnt++;
if (ccnt == n - 1) break;
}
}
printf("%.2lf", ans);
return 0;
}
应该是 d f s dfs dfs解决的,对于每一个 i i i点,我们去判断之前标记过的点和这个点会不会冲突(标记过说明这个点是可用的),如果这个点没有冲突的话,那么就标记这个点并且往下 d f s dfs dfs,复杂度应该是 O ( 2 n ) O(2^n) O(2n), n < = 30 n<=30 n<=30,所以肯定会超时的(写题解的时候突然醒悟了QAQ),所以可以加上剪枝,我们可以设一个后缀和,然后如果加上后缀和的值比最大值来的小,那么就可以直接 r e t u r n return return(个人想法,不知道对错),但是下面的代码还是可以混分的(手动滑稽)。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void out(int x) {
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
int Max = 0, n;
int x[50], y[50], r[50];
bool book[50] = {false};
int pow2(int x) {return x * x;}
bool check(int i, int j) {
if (r[i] + r[j] > sqrt(pow2(x[i] - x[j]) + pow2(y[i] - y[j]))) return false;
else return true;
}
void dfs(int step, int val) {
if (step == n) {
Max = max(Max, val);
return ;
}
for (int i = step; i <= n; i++) {
bool flag = true;
for (int j = 0; j < step; j++) {
if (book[j] && check(i, j) == false) {
flag = false;
break;
}
}
if (flag) {
book[i] = true;
dfs(i + 1, val + pow2(r[i]));
book[i] = false;
}
}
}
int main() {
read(n);
for (int i = 0; i < n; i++) read(x[i]), read(y[i]), read(r[i]);
dfs(0, 0);
printf("%d", Max);
return 0;
}