直接放代码吧。数组
int n,k; int main() { n=read();k=read(); puts(k<=(n+1)/2?"YES":"NO"); return 0; }
int d[N];pair<int,int>s[10]; int main() { for(int i=1,u,v;i<=3;i++){ u=read();v=read(); s[i].first=u;s[i].second=v; d[u]++;d[v]++; } sort(s+1,s+3+1); for(int i=2;i<=3;i++)if(s[i]==s[i-1])return puts("NO"),0; for(int i=1;i<=4;i++)if(d[i]>=3)return puts("NO"),0; return puts("YES"),0; }
int main() { int k=read(),a=read(),b=read();ll ans=0; if(b<=a+2||k<=a-1)printf("%d\n",k+1); else{ k-=a-1;ans=a;if(k&1)k--,ans++; printf("%lld\n",ans+1ll*(k/2)*(b-a)); } return 0; }
zsy在一条\([0,L]\)的数轴上来回走路。
zsy能够任选\([0,L]\)中的整点做为起点和终点,而且zsy走路时只能在整数位置(\(0,1,2,...,L\))调整方向。
每当zsy向左或向右通过一条\([i,i+1]\ (i\in[0,L))\)的线段时,zsy就会往这条线段的中间放上一个球。
当zsy走完路后,yyb会来到这条数轴。她会进行若干次操做:打爆一个球或在一条线段的中间放上一个球。
如今给出数轴每条线段中间最终球的个数\(a_1,...,a_n\),求出zsy的一种行走方式,使得yyb的操做次数最小。spa
由于zsy能够反复横跳来回地走,因此能够把\(a_i\)减去若干个2,最后只剩下\(0,1,2\)三种状态。
能够知道对应简化数组的一种最优方案里zsy不会重复走过一条路超过2次。
既然是回路问题,考虑插头dp。
设\(f[i][j][k]\)表示考虑轮廓线到达\(i\),插头有\(j\)个,已经用了\(k\)个单插头的最少代价,
直接转移便可。code
int n,t[N];ll suft[N],dp[N][3][3],ans; inline void upd(ll &a,ll b){a=a<b?a:b;} inline int calc(int x,int r){ if(r==0)return x; if(r==1)return x&1?0:1; if(r==2){if(!x)return 2;else return x&1?1:0;} } int main() { n=read();for(int i=1;i<=n;i++)t[i]=read(); for(int i=n;i;i--)suft[i]=suft[i+1]+t[i];ans=suft[1]; memset(dp,63,sizeof(dp));dp[0][0][0]=0; for(int i=0;i<=n;i++) for(int a=0;a<3;a++) for(int b=0;b<3;b++){ if(a==0){ upd(dp[i+1][a][b],dp[i][a][b]+t[i+1]); if(b!=2)upd(dp[i+1][a+1][b+1],dp[i][a][b]+calc(t[i+1],1)); upd(dp[i+1][a+2][b],dp[i][a][b]+calc(t[i+1],2)); } if(a==1){ if(b!=2)upd(ans,dp[i][a][b]+suft[i+1]); upd(dp[i+1][a][b],dp[i][a][b]+calc(t[i+1],1)); if(b!=2)upd(dp[i+1][a+1][b+1],dp[i][a][b]+calc(t[i+1],2)); } if(a==2){ upd(ans,dp[i][a][b]+suft[i+1]); if(b!=2)upd(dp[i+1][a-1][b+1],dp[i][a][b]+calc(t[i+1],1)); upd(dp[i+1][a][b],dp[i][a][b]+calc(t[i+1],2)); } } printf("%lld\n",ans); return 0; }
考虑给定行后选出列集合的方案数:
若是行的异或和不为0,那么总有一半的方案选出来异或和为1,另外一半为0,所以方案为\(2^{m-1}\)
因而答案变成\(2^{m-1}S\),其中\(S\)表示行向量选出来的异或和不为\(0\)的方案数。
求解选取行向量集合,使其异或和不为0的方案数是一个经典问题:
考虑求出\(n\)个行向量的线性基,设其大小为\(r\)。
若是仅选取线性基中的元素,显然没法使得异或和为\(0\);
那么考虑先选取不在线性基中的元素:
对于这样的一组方案,在线性基中都有惟一的一种选取元素的方案,使得全部元素的异或和为0.
所以\(S=2^n-2^{n-r}\)。class
int n,m,a[N][N],now[N],in[N],p[N][N],r; inline int poww(int a,int b){ int res=1; for(;b;b>>=1,a=1ll*a*a%mod) if(b&1)res=1ll*res*a%mod; return res; } int main() { n=read();m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)a[i][j]=read(); for(int i=1;i<=n;i++){ memcpy(now,a[i],sizeof(now)); for(int j=1;j<=m;j++) if(now[j]){ if(in[j])for(int k=j;k<=m;k++)now[k]^=p[j][k]; else{in[j]=1;memcpy(p[j],now,sizeof(p[j]));r++;break;} } } printf("%lld\n",1ll*(poww(2,n)-poww(2,n-r)+mod)%mod*poww(2,m-1)%mod); return 0; }
考虑直接构造最终序列。由传球方式能够知道,第\(i(i\le n)\)个球只会在\(1-i\)我的的手中出现,后\(n\)个求随意。
所以直接设\(f[i][j]\)dp,最后组合数乘一下便可。sort
char s[N];int n,dp[N][N],c[N][N],ans; inline void upd(int &a,int b){a+=b;if(a>=mod)a-=mod;} int main() { scanf("%s",s+1);n=strlen(s+1); for(int i=0;i<=n;i++) for(int j=c[i][0]=1;j<=i;j++)upd(c[i][j]=c[i-1][j],c[i-1][j-1]); dp[0][0]=1; for(int i=1;i<=n;i++) for(int j=0,c=s[i]-48;j<=i;j++){ if(j>=c-1)upd(dp[i][j],dp[i-1][j-c+1]); if(j>=c)upd(dp[i][j],dp[i-1][j-c]); } for(int i=0;i<=n;i++)upd(ans,1ll*dp[n][i]*c[n][i]%mod); printf("%d\n",ans); return 0; }