A
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int qq = 1e5 + 10;
int num[5] = {8, 4 , 2, 6};
int main(){
int n; scanf("%d", &n);
if(n == 0){
printf("1\n");
return 0;
}
printf("%d\n", num[(n-1)%4]);
return 0;
}
B
统计和查询
类似于前缀
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int qq = 1e7 + 10;
ll num[qq];
ll vis[qq];
map<int, int> Q;
int main(){
ll n, x; scanf("%lld%lld", &n, &x);
for(int i = 1; i <= n; ++i)
scanf("%lld", num+i);
ll sum = 0;
for(int i = 1; i <= n; ++i){
if(Q.find(x^num[i]) != Q.end()) sum += Q[x^num[i]];
Q[num[i]]++;
}
printf("%lld\n", sum);
return 0;
}
C
我到今天才理解题意...
找一个最小的t, 从一个点x走t次到达点y那么你走t的话一定要到达x, 也就是说你每次只能走t次, 而且对于x->y 一定存在 y->x
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int qq = 100 + 10;
int vis[qq];
int id[qq];
int n;
int gcd(int a, int b){
return b==0?a:gcd(b, a%b);
}
int lcm(int a, int b){
return a/gcd(a, b)*b;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%d", id+i);
vis[id[i]]++;
}
bool flag = true;
for(int i = 1; i <= n; ++i)
if(vis[i] == 0) flag = false;
if(!flag){
printf("-1\n");
return 0;
}
int minx = 1;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; ++i){
if(vis[i]) continue;
int start = i;
int p = i;
int count = 1;
vis[p] = 1;
while(vis[id[p]] != 1){
vis[id[p]] = 1;
p = id[p];
++count;
}
if(id[p] == start){
minx = lcm(minx, count);
}else{
printf("-1\n");
return 0;
}
}
printf("%d\n", minx);
return 0;
}
D
一个很裸的分组背包
并查集找联通块分组, 然后直接dp
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <map>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int qq = 1e3 + 10;
ll num[qq];
ll pre[qq];
ll n, m, k;
ll w[qq], b[qq];
int find(int x){
return pre[x]==x?x:pre[x]=find(pre[x]);
}
vector<ll> vw[qq], vb[qq];
ll dp[qq];
int main(){
scanf("%lld%lld%lld", &n, &m, &k);
for(int i = 0; i < n; ++i) scanf("%lld", w+i);
for(int i = 0; i < n; ++i) scanf("%lld", b+i);
for(int i = 0; i <=n; ++i) pre[i] = i;
for(int i = 0; i < m; ++i){
int a, b;scanf("%d%d", &a, &b);
a--,b--;
int x = find(a), y = find(b);
if(x == y) continue;
pre[y] = x;
}
queue<int> Q[qq];
for(int i = 0; i < n; ++i)
Q[find(i)].push(i);
int p = 0;
for(int i = 0; i < n; ++i){
if(Q[i].size() == 0) continue;
ll sum1, sum2;
sum1 = sum2 = 0;
while(!Q[i].empty()){
vw[p].push_back(w[Q[i].front()]);
vb[p].push_back(b[Q[i].front()]);
sum1 += w[Q[i].front()];
sum2 += b[Q[i].front()];
Q[i].pop();
}
vw[p].push_back(sum1);
vb[p].push_back(sum2);
p++;
}
memset(dp, -1, sizeof(dp));
dp[0] = 0;
for(int i = 0; i < p; ++i)
for(int j = k; j >= 0; --j)
for(int l = 0; l < (ll)vw[i].size(); ++l){
if(j-vw[i][l] < 0) continue;
if(dp[j-vw[i][l]] != -1)
dp[j] = max(dp[j], dp[j-vw[i][l]]+vb[i][l]);
}
ll maxn = -1;
for(int i = 0; i <= k; ++i) maxn = max(maxn, dp[i]);
printf("%lld\n", maxn);
return 0;
}