A. Arpa’s hard exam and Mehrdad’s naive cheat
题意
求 1378n 的末位数字, 0≤n≤109
分析
尾数的循环节, 6,8,4,2
HINT: 13780 需要特判
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a[] = {6,8,4,2};
scanf("%d",&n);
if(n == 0) printf("1\n");
else printf("%d\n",a[n%4]);
}
B. Arpa’s obvious problem and Mehrdad’s terrible solution
题意
有n个数字分别为 a1,a2,…,an (1≤ai≤105) ,问有多少组合使得 ai⨂aj=x 成立
分析
由于 ai∈[1,105] ,故统计对应数字的个数
遍历 [1,105] ,通过 i⨂x 计数
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 200000 + 1;
int cnt[N];
int main(){
int n,x;
scanf("%d %d",&n,&x);
for(int i=0,a;i<n;i++)
scanf("%d",&a), cnt[a]++;
long long ans = 0;
if(x){
for(int i=0;i<100001;i++)
if(cnt[i] && cnt[i^x])
ans += (long long)cnt[i]*cnt[i^x];
}else{
for(int i=0;i<100001;i++)
ans += (long long)cnt[i] * (cnt[i]-1);
}
printf("%I64d\n",ans/2);
}
C. Arpa’s loud Owf and Mehrdad’s evil plan
题意
定义操作: Owf为x通过 x→crush[x]→crush[crush[x]]→…→y 其中转移t次
满足 y→crush[y]→crush[crush[y]]→…→x
问最小的t使得所有数 [1,n] 均满足上述操作
分析
若转移次数为奇数,则必须 x=y
若转移次数为偶数,则可取中间值使得 x→y 与 y→x 均转移t次即可
求最小公倍数
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 100+10;
int crush[N],n,cnt;
bool vis[N];
bool dfs(int idx,int st){
if(idx == st) return true;
if(vis[idx]) return false;
vis[idx] = 1; cnt++;
dfs(crush[idx],st);
}
long long solve(){
long long ans = 1;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
cnt = 1;
bool flag = dfs(crush[i],i);
if(!flag) return -1;
if(cnt % 2 == 0) cnt /= 2;
ans = ans * cnt / __gcd(ans,(long long)cnt);
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&crush[i]);
printf("%I64d\n",solve());
}
D. Arpa’s weak amphitheater and Mehrdad’s valuable Hoses
Description
Mehrdad wants to invite some Hoses to the palace for a dancing party. Each Hos has some weight
wi
and some beauty
bi
. Also each Hos may have some friends. Hoses are divided in some friendship groups. Two Hoses
x
and
Arpa allowed to use the amphitheater of palace to Mehrdad for this party. Arpa’s amphitheater can hold at most w weight on it.
Mehrdad is so greedy that he wants to invite some Hoses such that sum of their weights is not greater than w and sum of their beauties is as large as possible. Along with that, from each friendship group he can either invite all Hoses, or no more than one. Otherwise, some Hoses will be hurt. Find for Mehrdad the maximum possible total beauty of Hoses he can invite so that no one gets hurt and the total weight doesn’t exceed w.
题意
抽象成背包问题
背包容量为w,现在有若干组物品,每组若干件物品,每件物品的体积为
分析
分组的背包问题,详解见背包九讲
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1000 + 10;
const int V = 1000 + 10;
int w[N],b[N],dp[V],fa[N];
vector<int> vec[N];
int find(int x){
return fa[x] = fa[x] == x ? x : find(fa[x]);
}
void Union(int x,int y){
int fx = find(x), fy = find(y);
if(fx > fy) swap(fx,fy);
fa[fy] = fx;
}
int main(){
int n,m,W;
scanf("%d %d %d",&n,&m,&W);
for(int i=1;i<=n;i++) fa[i] = i;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
for(int i=0,x,y;i<m;i++) scanf("%d %d",&x,&y), Union(x,y);
for(int i=1;i<=n;i++) vec[find(i)].push_back(i);
for(int i=1;i<=n;i++){
if(vec[i].size() == 0) continue;
for(int v=W;v;v--){
int totW = 0, totB = 0;
for(int j=0;j<vec[i].size();j++){
if(v >= w[vec[i][j]])
dp[v] = max(dp[v],dp[v-w[vec[i][j]]] + b[vec[i][j]]);
totW += w[vec[i][j]];
totB += b[vec[i][j]];
}
if(v >= totW)
dp[v] = max(dp[v],dp[v-totW] + totB);
}
}
printf("%d\n",dp[W]);
}
E. Arpa’s overnight party and Mehrdad’s silent entering
题意
已知n对情侣,编号分别为 [1,2×n] 中的一个(保证一个编号对应一人)
问是否能对每个人分配食物Kooft或Zahre-mar,使得:
- 每个人都能分配到Kooft或Zahre-mar
- 每对情侣分配到的食物必然不同
- 对于任意连续的3个人,必然有两人的食物是不同的。(Note:编号2n视作与编号1相邻)
给出一种可行方案即可。
分析
感觉很神奇的题。竟然可以转化为二分图…
关键在于要点3
。对连续3人,使得必然有一个人的食物与其他两人不同,则其可能方案为1 1 2
, 1 2 1
, 2 1 1
其中1
与2
的整体替换对最终答案没有影响。通过枚举可能情况可以发现,对连续3人食物的要求,可以转化为求相邻两人的情况,即要点3
可以看作是使得编号为i*2
与i*2+1
的两人的食物不同
此时,该问题即可转换为二分图染色
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int E = N + N;
int n,a[N],b[N],cnt = 0,head[N*2],arr[N*2];
struct Edge{
int to,nxt;
}e[E*2];
void addedge(int u,int v){
e[++cnt].nxt = head[u];
e[cnt].to = v;
head[u] = cnt;
}
bool dfs(int idx){
for(int i=head[idx],to;i;i=e[i].nxt){
to = e[i].to;
if(arr[to]){
if(arr[to] == arr[idx])
return false;
continue;
}
arr[to] = 3-arr[idx];
if(!dfs(to)) return false;
}
return true;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d %d",&a[i],&b[i]), addedge(a[i],b[i]), addedge(b[i],a[i]);
for(int i=1;i<=n;i++)
addedge(i*2,i*2+1), addedge(i*2+1,i*2);
bool flag = 1;
for(int i=1;i<=2*n;i++)
if(arr[i] == 0 && (arr[i] = 1) && !dfs(i)){
flag = 0; break;
}
if(!flag) printf("-1");
else{
for(int i=1;i<=n;i++)
printf("%d %d\n",arr[a[i]],arr[b[i]]);
}
}