A:奇偶配对。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 100010 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,m,a[N],b[N]; signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(); int x1=0,x2=0,y1=0,y2=0; for (int i=1;i<=n;i++) { a[i]=read(); x1+=a[i]&1,x2+=a[i]&1^1; } for (int i=1;i<=m;i++) { b[i]=read(); y1+=b[i]&1,y2+=b[i]&1^1; } cout<<min(x1,y2)+min(x2,y1); return 0; //NOTICE LONG LONG!!!!! }
B:从高位到低位考虑,每遇到一个0就考虑将其改成1,即如果该位之后全是0就改下一位,否则改这一位。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 1000010 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,ans[100],t; signed main() { n=read(); for (int i=19;i>=0;i--) if (!(n&(1<<i))) { if (((n>>i)<<i)==n) { ans[++t]=i; n^=(1<<i)-1;n++; } else { ans[++t]=i+1; n^=(1<<i+1)-1;n++; } } cout<<t*2<<endl; for (int i=1;i<=t;i++) cout<<ans[i]<<' '; return 0; //NOTICE LONG LONG!!!!! }
C:显然无论如何变化两者gcd一定是a-b的因子。确定gcd(是某数倍数)的情况下很容易求出最小k。枚举每个因子取最优解即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 1000010 #define pii pair<ll,int> #define mp(x,y) make_pair((x),(y)) int a,b; pii ans; pii calc(int x) { int t=(x-a%x)%x; return mp(1ll*(a+t)*(b+t)/x,t); } signed main() { cin>>a>>b; if (a<b) swap(a,b);if (a==b) {cout<<0;return 0;} ans.first=1ll*inf*inf;ans.second=inf; for (int i=1;i*i<=a-b;i++) if ((a-b)%i==0) ans=min(ans,calc(i)),ans=min(ans,calc((a-b)/i)); cout<<ans.second; return 0; //NOTICE LONG LONG!!!!! }
D:做法似乎非常多。考虑n++后树形态的变化。可以发现是给当前所有没有左儿子的点添加左儿子,并给该左儿子一直添加右儿子直至所有叶子节点深度相同。任意时刻没有左儿子的点都构成很多条链,上述过程就是这些链所引发的,可以考虑dp出各种长度的链的条数,转移考虑上述过程即可。然后考虑怎么利用这个东西求出答案。这棵树的最大匹配可以自底向上贪心求得。画画图观察一下,容易发现最大匹配中各层间是无关的,即上述过程的第一步所添加的边选进最大匹配不会更优。那么一条链对最大匹配的贡献就是链上点的个数/2了。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 1010 #define P 1000000007 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,f[N][N],g[N][N],ans; signed main() { n=read(); f[0][1]=1;for (int j=0;j<=n+1;j++) g[0][j]=1; for (int i=1;i<=n;i++) { for (int j=2;j<=i+1;j++) { f[i][j]=g[i-1][j-1]; ans=(ans+1ll*f[i][j]*(j>>1))%P; } for (int j=n+1;j>=0;j--) g[i][j]=(g[i][j+1]+f[i][j])%P; } cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
E:除开头和结尾位置上的数都会在给出的数组中的相邻位置出现两次,开头和结尾会各出现一次。将每个数看成一个点,给出的每对数看成一条边,就相当于找一条欧拉路。跑出来再判一下是否合法即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #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,a[N],b[N],p[N],u[N<<1],ans[N],tot,degree[N],cnt,t=-1,top; bool flag[N]; map<int,int> f[N]; 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) if (!flag[i>>1]) { flag[i>>1]=1; p[k]=edge[i].nxt; cnt++; dfs(edge[i].to); ans[top--]=edge[i].to; if (cnt==n-1) break; } } signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read();memset(p,255,sizeof(p)); for (int i=1;i<n;i++) u[++tot]=a[i]=read(); for (int i=1;i<n;i++) u[++tot]=b[i]=read(); sort(u+1,u+tot+1); tot=unique(u+1,u+tot+1)-u-1; for (int i=1;i<n;i++) a[i]=lower_bound(u+1,u+tot+1,a[i])-u; for (int i=1;i<n;i++) b[i]=lower_bound(u+1,u+tot+1,b[i])-u; for (int i=1;i<n;i++) addedge(a[i],b[i]),addedge(b[i],a[i]),degree[a[i]]++,degree[b[i]]++,f[a[i]][b[i]]++; int qwq=0; for (int i=1;i<=tot;i++) if (degree[i]&1) qwq++; if (qwq!=2&&qwq!=0) {cout<<-1;return 0;} top=n;for (int i=1;i<=tot;i++) if (qwq==0||(degree[i]&1)) {dfs(i);ans[1]=i;break;} for (int i=1;i<n;i++) if (f[min(ans[i],ans[i+1])][max(ans[i],ans[i+1])]==0) {cout<<-1;return 0;} else f[min(ans[i],ans[i+1])][max(ans[i],ans[i+1])]--; for (int i=1;i<=n;i++) printf("%d ",u[ans[i]]); return 0; //NOTICE LONG LONG!!!!! }
F:由于要求每个数各不相同,考虑按数的顺序dp。不妨考虑从大到小。则每次向序列中插入一个数时,需要满足其后一个数-m<=该数。于是设f[i][j][k]为插入i后序列中有j个数其中i~i+m-1在序列中的存在性为k。矩阵快速幂优化。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define P 1000000007 #define N 210 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,m,k,ans,size[N]; struct matrix { int n,a[N][N]; matrix operator *(const matrix&b) const { matrix c;c.n=n;memset(c.a,0,sizeof(c.a)); for (int i=0;i<n;i++) for (int j=0;j<b.n;j++) for (int k=0;k<b.n;k++) c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j])%P; return c; } }f,a; int trans(int x,int y){return (x<<m)+y;} signed main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),k=read(),m=read(); f.n=1;f.a[0][0]=1; a.n=k+1<<m; for (int i=1;i<(1<<m);i++) size[i]=size[i^(i&-i)]+1; for (int i=0;i<=k;i++) for (int j=0;j<(1<<m);j++) { a.a[trans(i,j)][trans(i,(j<<1)&(1<<m)-1)]++; if (i<k) a.a[trans(i,j)][trans(i+1,((j<<1)&(1<<m)-1)|1)]+=size[j]+1; } for (;n;n>>=1,a=a*a) if (n&1) f=f*a; for (int j=0;j<(1<<m);j++) ans=(ans+f.a[0][trans(k,j)])%P; cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
小小小号打的。result:rank 248 rating +166 彻底自闭.jpg