A.排序即可 #include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int maxn=10010; int n; long long a[maxn],sum[maxn]; int main() { scanf("%d",&n); for (int i=1;i<=2*n;i++) scanf("%lld",&a[i]); sort(a+1,a+2*n+1); for (int i=1;i<=2*n;i++) sum[i]=sum[i-1]+a[i]; if (2ll*sum[n]==sum[2*n]) return printf("-1\n"),0; for (int i=1;i<=2*n;i++) printf("%lld ",a[i]); return 0; }
B.将奇数偶数分开考虑,只有偶数和奇数之间可以做交换
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int maxn=100010; int n,a[maxn],b[maxn],c[maxn],ans[maxn],pb,pc,ppb,ppc; int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); if (a[i]&1) b[++pb]=a[i];else c[++pc]=a[i]; } if (pb) sort(c+1,c+pc+1); if (pc) sort(b+1,b+pb+1); ppb=ppc=1; for (int i=1;i<=n;i++) if (ppb==pb+1) ans[i]=c[ppc++]; else if (ppc==pc+1) ans[i]=b[ppb++]; else {if (b[ppb]<c[ppc]) ans[i]=b[ppb++];else ans[i]=c[ppc++];} for (int i=1;i<=n;i++) printf("%d ",ans[i]); return 0; }
C.线性筛出所有因子,具有相同因子的填一样的数
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> using namespace std; const int maxn=100010; int n,ans[maxn],p,prime[maxn],cnt; bool f[maxn]; int main() { scanf("%d",&n); p=1; memset(f,1,sizeof f); f[0]=f[1]=0; for (int i=2;i<=n;i++) { if (f[i]) prime[++cnt]=i; for (int j=1;j<=cnt && 1ll*i*prime[j]<=n;j++) { f[i*prime[j]]=0; if (i%prime[j]==0) break; } } for (int i=1;i<=cnt;i++) { for (int j=prime[i];j<=n;j+=prime[i]) if (!ans[j]) ans[j]=p; p++; } for (int i=2;i<=n;i++) printf("%d ",ans[i]); return 0; }
D.将每个位置的数看做是a^b,那么任意连续子段异或就变成了x^y,那么就变成了构造一个数列,使得两两互不相同,且异或不为x,然后真实序列就是这个序列的相邻项异或
#include <iostream> #include <cstdio> #include <cstdlib> #include <set> using namespace std; const int maxn=1000010; int n,x,ans[maxn],p[20],now; set<int>s; int main() { scanf("%d%d",&n,&x); p[0]=1; for (int i=1;i<=n;i++) p[i]=p[i-1]*2; if (x>=p[n]) { printf("%d\n",p[n]-1); for (int i=1;i<=p[n]-1;i++) printf("%d ",i^(i-1)); return 0; } printf("%d\n",p[n-1]-1); if (n==1) return 0; ans[0]=0; int pp=1; if (x==1) pp=2; s.insert(x); for (int i=1;i<=p[n-1]-1;i++) { ans[i]=pp; s.insert(pp^x); pp++; while (s.find(pp)!=s.end()) ++pp; } for (int i=1;i<=p[n-1]-1;i++) printf("%d ",ans[i]^ans[i-1]); return 0; }
E.dp[i][j][k]表示当前放到第i个位置,gcd的因子有j个2,k个3的方案数,转移的时候分三种方法转移:
1.dp[i+1][j][k]=(dp[i+1][j][k]+1ll*dp[i][j][k]*(calc(j,k)-i))%mo;
2.dp[i+1][j-1][k]=(dp[i+1][j-1][k]+1ll*dp[i][j][k]*(calc(j-1,k)-calc(j,k)))%mo;
3.dp[i+1][j][k-1]=(dp[i+1][j][k-1]+1ll*dp[i][j][k]*(calc(j,k-1)-calc(j,k)))%mo;
calc(x,y)计算1~n之间有多少个数的因子里有x个2,y个3
#include <iostream> using namespace std; const int mo=1e9+7; const int maxn=1000002; int n,t; int dp[maxn][21][2]; int calc(int a,int b){return n/((1<<a)*(b?3:1));} int main() { scanf("%d",&n); int p=0; while ((1<<(p+1))<=n) p++; dp[1][p][0]=1; if (((1<<(p-1))*3)<=n) dp[1][p-1][1]=1; for (register int i=1;i<n;i++) { for (register int j=0;j<=p;j++) for (register int k=0;k<=1;k++) { dp[i+1][j][k]=(dp[i+1][j][k]+1ll*dp[i][j][k]*(calc(j,k)-i))%mo; if (j) dp[i+1][j-1][k]=(dp[i+1][j-1][k]+1ll*dp[i][j][k]*(calc(j-1,k)-calc(j,k)))%mo; if (k) dp[i+1][j][k-1]=(dp[i+1][j][k-1]+1ll*dp[i][j][k]*(calc(j,k-1)-calc(j,k)))%mo; } } printf("%d\n",dp[n][0][0]); return 0; }
F.树剖之后每次在重链头上询问方向(s),在重链尾部询问距离(d),这样重链有log条,询问次数至多2log次
注意1:在1号点先问一次距离,每次用这个距离来判断当前重链头是不是要找的点(若是就直接输出而不是询问方向)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <cmath> using namespace std; const int maxn=200010; int n,m,st[maxn<<1],nt[maxn<<1],to[maxn<<1],topt; int si[maxn],rem[maxn],top[maxn],down[maxn],dep[maxn],fa[maxn],mm[maxn]; int dfn_num,dfn[maxn],line[maxn],d1,d2,ff[30][maxn],de; bool f[maxn],ok; inline void add(int x,int y){to[++topt]=y; nt[topt]=st[x]; st[x]=topt;} void dfs1(int x,int dd) { f[x]=1; dep[x]=dd; si[x]=1; int p=st[x],ma=0; while (p) { if (!f[to[p]]) { dfs1(to[p],dd+1); si[x]+=si[to[p]]; fa[to[p]]=x; ff[0][to[p]]=x; if (si[to[p]]>ma) {ma=si[to[p]]; rem[x]=to[p];} } p=nt[p]; } } void dfs2(int x) { f[x]=1; if (rem[fa[x]]==x) top[x]=top[fa[x]];else top[x]=x; if (mm[top[x]]<dep[x]) {mm[top[x]]=dep[x]; down[top[x]]=x;} int p=st[x]; if (rem[x]) dfs2(rem[x]); while (p) { if (!f[to[p]]) dfs2(to[p]); p=nt[p]; } } int find(int x,int k) { int p=0; if (k==0) return x; while ((1<<(p+1))<=k) p++; return find(ff[p][x],k-(1<<p)); } void work(int x,int dis) { if (ok) return; if (x==1) {printf("d %d\n",x); fflush(stdout); scanf("%d",&d1); de=d1;}else d1=dis; if (d1==0) {printf("! %d\n",x); ok=1; return;} if (d1==1) { printf("s %d\n",x); fflush(stdout); scanf("%d",&d1); printf("! %d\n",d1); fflush(stdout); ok=1; return; } printf("d %d\n",down[x]); fflush(stdout); scanf("%d",&d2); if (d2==0) {printf("! %d\n",down[x]); fflush(stdout); ok=1; return;} if (d1+d2==dep[down[x]]-dep[x]) {printf("! %d\n",find(down[x],dep[down[x]]-de)); fflush(stdout); ok=1; return;} else { int xx=find(down[x],dep[down[x]]-de+(d1+d2-(dep[down[x]]-dep[x]))/2); printf("s %d\n",xx); fflush(stdout); int now; scanf("%d",&now); work(now,de-dep[now]); } } int main() { scanf("%d",&n); for (int i=1;i<n;i++) { int xx,yy; scanf("%d%d",&xx,&yy); add(xx,yy); add(yy,xx); } dfs1(1,0); memset(f,0,sizeof f); dfs2(1); for (int i=1;i<=20;i++) for (int j=1;j<=n;j++) ff[i][j]=ff[i-1][ff[i-1][j]]; work(1,0); return 0; }