B:当n是偶数时无解,因为此时树中有奇数条边,而我们每次都只能删除偶数条。当n是奇数时一定有解,因为此时不可能所有点度数都为奇数,只要找到一个度数为偶数的点,满足将它删掉后,各连通块大小都为奇数就可以了。考虑如何证明这样的点一定存在。钦定一个根后,考虑找到一个度数为偶数的点,满足子树内点度数均为奇数。这样该点的所有儿子的子树都有奇数个点, 因为删掉该点后每个子树内只有一个点度数为偶数。又因为删掉这个点后该树剩下偶数个点和偶数个连通块,所以该点父亲所在连通块也有奇数个点。
于是只需要先自底向上删掉度数为偶数的点,再将剩余每棵树自顶向下删除即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,p[N],fa[N],degree[N],t,root; struct data{int to,nxt; }edge[N<<1]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void dfs(int k) { for (int i=p[k];i;i=edge[i].nxt) { dfs(edge[i].to); degree[k]+=(degree[edge[i].to]%2==0); } if ((degree[k]&1)==(k!=root)) printf("%d\n",k); } void dfs2(int k) { if ((degree[k]&1)!=(k!=root)) printf("%d\n",k); for (int i=p[k];i;i=edge[i].nxt) dfs2(edge[i].to); } signed main() { #ifndef ONLINE_JUDGE freopen("b.in","r",stdin); freopen("b.out","w",stdout); #endif n=read(); for (int i=1;i<=n;i++) { fa[i]=read(); if (fa[i]) addedge(fa[i],i); else root=i; } if (n%2==0) {cout<<"NO";return 0;} cout<<"YES"<<endl; dfs(root); dfs2(root); return 0; //NOTICE LONG LONG!!!!! }
C:对于每种矩形宽,找出其各种矩形长的出现次数。如果对某两种宽,其矩形长出现次数的比例不同,显然无解。然后对所有出现次数取gcd即可,gcd的因子数即为答案,即考虑每一行各种矩形长究竟出现了多少次。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} ll gcd(ll n,ll m){return m==0?n:gcd(m,n%m);} ll read() { ll x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,tot; ll ans; struct data { ll x,y,z; bool operator <(const data&a) const { return x<a.x||x==a.x&&y<a.y; } }a[N]; void error(){cout<<0;exit(0);} signed main() { #ifndef ONLINE_JUDGE freopen("c.in","r",stdin); freopen("c.out","w",stdout); #endif n=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].z=read(),ans=gcd(ans,a[i].z); sort(a+1,a+n+1); int len=0; for (int i=1;i<=n;i++) if (a[i].x==a[1].x) len++;else break; if (n%len) error(); for (int i=1;i<=n;i+=len) { ll x=0;if (a[i].x==a[i-1].x) error(); for (int j=i;j<i+len;j++) { x=gcd(x,a[j].z); if (i>len&&(a[j].x!=a[i].x||a[j].y!=a[j-len].y)) error(); } for (int j=i;j<i+len;j++) { a[j].z/=x; if (i>len&&a[j].z!=a[j-len].z) error(); } } for (ll i=1;i*i<=ans;i++) if (ans%i==0) { tot++; if (i*i!=ans) tot++; } cout<<tot; return 0; //NOTICE LONG LONG!!!!! }