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