2018-2019 XIX Open Cup, Grand Prix of Korea
E Electronic Circuit
题目链接
题意:给出n个点,m条边的图,要求判断是否存在源点、汇点使得图满足简单电路、仅存在串联和并联。
思路:对于a->b->c的路径可以压缩为a->b,不断压缩后判断是否只有源点和汇点,即为判断是否为简单电路。
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m,cnt;
int u,v;
set <int>G[maxn];
int book[maxn];
void del(int x){
if(G[x].size()==2){
book[x]=1;
cnt--;
int y = *G[x].begin();
int z = *G[x].rbegin();
G[y].erase(x);
G[z].erase(x);
G[y].insert(z);
G[z].insert(y);
if (!book[y]) del(y);
if (!book[z]) del(z);
}
}
void input(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
G[u].insert(v);
G[v].insert(u);
}
}
void solve(){
cnt=n;
for(int i=1;i<=n;i++)
{
if(!book[i]){
del(i);
}
}
printf(cnt==2?"Yes\n":"No\n");
}
int main(){
input();
solve();
} F Fake Plastic Trees
题目链接
题意:要求构建一颗二叉树,每个节点的左节点的叶子数只能比右结点叶子数大于1或者等于。对于每个节点进行编号,要求节点编号大靠近根,节点编号小靠近叶子。若节点的左右节点连的相同可看作相同节点,对于节点hash后输出
思路:对于一个叶子节点为n的节点,若n为奇数,可以满足左节点叶子节点数为n/2+1,右结点为n/2。若n为偶数,可以分配左右节点的叶子节点数都为n/2。这个策略满足题目条件且满足节点个数不超过125。指数型下降。用dfs构造即可
#include <bits/stdc++.h>
#include<vector>
typedef long long ll;
using namespace std;
map <ll,int>ma;
map <ll,int>ind;
struct node{
ll val;
ll l,r;
}nod[205];
int cnt;
bool cmp(node a,node b){
return a.val<b.val;
}
void dfs(ll n){
if(ma[n])
return;
ma[n]=1;
nod[cnt].val=n;
// cout<<cnt<<' '<<n<<endl;
if(n==1)
{
nod[cnt].l=-1;
nod[cnt].r=-1;
cnt++;
return;
}
if(n%2==0){
nod[cnt].l=n/2;
nod[cnt].r=n/2;
cnt++;
dfs(max(1ll,n/2));
}
else{
nod[cnt].l=n/2+1;
nod[cnt].r=n/2;
cnt++;
dfs(n/2+1);
dfs(n/2);
}
}
int main(){
int t;
ll n;
scanf("%d",&t);
while(t--){
cnt=0;
ma.clear();
ind.clear();
scanf("%lld",&n);
dfs(n);
sort(nod,nod+cnt,cmp);
printf("%d\n",cnt);
ind[-1]=-1;
for(int i=0;i<cnt;i++){
ind[nod[i].val]=i;
printf("%d %d\n",ind[nod[i].l],ind[nod[i].r]);
}
printf("%d\n",ind[nod[cnt-1].val]);
}
return 0;
} H Fractions
题目链接
题意:给定A,B,C,D。x包含于[A,B]且y包含于[C,D],求对于x和y,满足x/y化为最简后x+y<1000的(x,y)点对
思路:通过n^2的判断可以将1000以内满足互质且x+y<1000的数预处理出来。对于我们已知的点对(x,y),寻找并且
,经过化简得出
并且
。对于两个区间求交。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1004][1003];
ll gcd(ll a, ll b) {
return b ? gcd(b, a%b) : a;
}
void init() {
for (ll i = 1; i <= 1000; i++) {
for (ll j = 1; i + j < 1000; j++) {
if (gcd(i, j) != 1)continue;
a[i][++a[i][0]] = j;
}
}
}
ll solve(ll A, ll B, ll C, ll D) {
ll ans = 0;
for (ll i = 1; i <= 1000; i++) {
for (ll jj = 1; jj <= a[i][0]; jj++) {
ll j = a[i][jj];
ll l1 = (A + i - 1) / i;
ll l2 = (C + j - 1) /j;
ll r1 = (B) / i;
ll r2 = (D) / j;
// cout << l1 << " " << r1 << " " << l2 << " " << r2 << endl;
ans += max(min(r1, r2) - max(l1, l2) + 1, 0ll);
//cout << "* " << ans << endl;
}
}
return ans;
}
int main() {
init();
ll A, B, C, D;
scanf("%lld%lld%lld%lld", &A, &B, &C, &D);
printf("%lld\n", solve(A, B, C, D));
} I Game on Plane
题目链接
题意:对于n个点的正n边形,先手后手选择两个点连边,要求边不与之前边相交,且不能构成凸多边形。当不可连边时则失败。求先手后手谁赢
思路:SG函数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<string>
#include<cmath>
#include<stack>
#include<functional>
#include<bitset>
#define ll long long
#define maxn 100002
const int INF = 0x3f3f3f3f;
using namespace std;
int s[5002], sg[5002];
int main(void){
int t, n, i, j;
sg[1] = 0;
sg[2] = 1;
for(i = 3;i <= 5000;i++){
for(j = 0;j <= 5000;j++){
s[j] = 0;
}
for(j = 0;j * 2 <= i - 2;j++){
s[sg[j] ^ sg[i - 2 - j]] = 1;
}
for(j = 0;j <= 5001;j++){
if(!s[j]){
sg[i] = j;
break;
}
}
}
scanf("%d",&t);
while(t--){
scanf("%d",&n);
if(sg[n]){
puts("First");
}
else{
puts("Second");
}
}
return 0;
} L Timsort
题目链接
题意:Timsort将区间分割为每个大小minrun以上的区域,并且保证在同一个区间里的数要么满足非递减、要么满足递减。当一个区间的数不满足非递减或者递减且小于minrun时,就用坏点。求最后多少个区间、多少个坏点。
思路:对于一个非递减或者递减区间、通过前两位数字即可得到。通过并查集可以快速寻找到最远的区间右点。
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
int fa1[maxn];
int fa2[maxn];
int a[maxn];
int n;
struct node{
int l,r;
int flag;
}an[maxn];
void init(int x){
for(int i=1;i<=x;i++)
fa1[i]=fa2[i]=i;
}
int find1(int x){
return x==fa1[x]?x:fa1[x]=find1(fa1[x]);
}
int find2(int x){
return x==fa2[x]?x:fa2[x]=find2(fa2[x]);
}
void mix1(int x,int y){
int fx=find1(x);
int fy=find1(y);
fa1[fx]=fy;
}
void mix2(int x,int y){
int fx=find2(x);
int fy=find2(y);
fa2[fx]=fy;
}
void input(){
scanf("%d",&n);
init(n);
int i;
for(i=1;i<=n;i++){
//a[i] = i & 1;
scanf("%d",&a[i]);
}
for(i=2;i<=n;i++){
if(a[i]>=a[i-1])
mix1(i-1,i);
else
mix2(i-1,i);
}
}
void solve(){
int q,x;
scanf("%d",&q);
//q = 100000;
for(int i=1;i<=q;i++){
//x = 2;
scanf("%d",&x);
if(an[x].flag){
printf("%d %d\n",an[x].l,an[x].r);
continue;
}
int ind1,ind2;
int ans,bad;
ans=bad=0;
ind1=1;
while(ind1<=n){
ind2=min(n,ind1+x-1);
int pos=max(find1(ind1),find2(ind1));
// cout<<ind1<<' '<<ind2<<' '<<pos<<endl;
if(pos<ind2){
bad+=ind2-pos;
ind1=ind2+1;
}else
ind1=pos+1;
ans++;
}
printf("%d %d\n",ans,bad);
an[x].l=ans;
an[x].r=bad;
an[x].flag=1;
}
}
int main(){
input();
solve();
}
京公网安备 11010502036488号