(部分是)2019.2.27交流题,题目顺序瞎排的
codeM2017初赛B轮D题
这为啥会放进省选作业里啊=。=
这不就是问你$gcd(a,k-1) equiv c(mod$ $b)$有没有解吗,裴蜀定理,没了
代码不放了
CF724E Goods transportation
咦,这不是wxx以前交流的时候讲的题吗=。=
WF2012 infiltration
乱搞题,主要是要发现答案不超过log,然后1-5暴力判,其余输出6
代码不放了
CF547D Mike and fish
每条鱼的行列对应连边,构成一张二分图。这个题说明了:给一张二分图边黑白染色,使得每个节点的黑白边数相差不超过1,是一定可行的。原因大概是(口胡)二分图里没有奇环,所以DFS涂色,要么是交替涂了一个偶环,每个点的黑白边差不变;要么涂了一条链,只有端点变化了1,只要在下次它又做端点时涂另一种颜色即可。
具体实现差不多,先涂奇节点,然后直接涂,看代码吧
1 #include<set> 2 #include<map> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #define pii pair<int,int> 7 using namespace std; 8 const int N=400005,M=2e5; 9 int n,x[N],y[N]; 10 set<int> p[N]; 11 map<pii,int> r; 12 void DFS(int nde) 13 { 14 if(p[nde].empty()) return; 15 int nxt=*p[nde].begin(); 16 p[nde].erase(nxt),p[nxt].erase(nde); 17 r[make_pair(nde,nxt)]=true; DFS(nxt); 18 } 19 int main() 20 { 21 scanf("%d",&n); 22 for(int i=1;i<=n;i++) 23 { 24 scanf("%d%d",&x[i],&y[i]); 25 p[x[i]].insert(y[i]+M); 26 p[y[i]+M].insert(x[i]); 27 } 28 for(int i=1;i<=2*M;i++) 29 if(p[i].size()%2) DFS(i); 30 for(int i=1;i<=2*M;i++) 31 while(!p[i].empty()) DFS(i); 32 for(int i=1;i<=n;i++) 33 r[make_pair(x[i],y[i]+M)]?putchar('r'):putchar('b'); 34 return 0; 35 }
NOI 2017 泳池
吉如一的神仙题
先说式子怎么推的
zlk:dp不出来的,后容斥一下就能dp了
等于不好求,我们求小于等于然后作差
设$dp[i][j]$表示一个宽$i$高$j$的矩形,其中$j-1$行及以下全部安全,第$j$行存在不安全区域,整个矩形里的全部安全的子矩形大小不超过$k$的概率。转移是枚举第一个不安全的那个区域在哪,这里设安全的概率是$p$,那么有
$dp[i][j]=p^{j-1}(1-p) sumlimits_{k=1}^i(sum_{h>j}dp[k-1][h])(sum_{h>=j}dp[i-k][h]) (i*(j-1)<=k)$
用后缀和优化一下就可以$O(k^2)$求出来了,然后再求我们的答案$ans$。设$ans[i]$表示宽为$i$时的答案,在最底下一行枚举拼合点前后拼起来,再加上整段的情况
$ans[i]=dp[i][2]+sumlimits_{j=1}^n ans[i-j]*dp[j-1][2]*(1-p)$
我们终于得到了一个$O(nk)$的做法,可喜可贺,可喜可贺
好啊,矩阵乘法!再一看k=1000......
这个求ans的过程是一个常系数线性递推,为了避免这篇题目汇总过长,我把常系数线性递推单独开个模板写,这里只需要$O(k^2)$多项式取模的方法就可以通过了。算上快速幂总复杂度$O(k^2log n)$
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1005,mod=998244353; 6 int m,k,x,y,p,pp,dp[N],pw[N],mo[N],mu[N],cal[2*N],ret[N],f[N][N]; 7 void Add(int &x,int y) 8 { 9 x+=y; 10 if(x>=mod) x-=mod; 11 } 12 int Qpow(int x,int k) 13 { 14 if(k==1) return x; 15 int tmp=Qpow(x,k/2); 16 return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod; 17 } 18 void Polymul(int *a,int *b,int *m,int *r,int len) 19 { 20 for(int i=0;i<=len;i++) 21 for(int j=0;j<=len;j++) 22 Add(cal[i+j],1ll*a[i]*b[j]%mod); 23 for(int i=2*len;i>=len;i--) 24 if(cal[i]) 25 for(int j=0;j<=len;j++) 26 Add(cal[i+j-len],mod-1ll*cal[i]*m[j]%mod); 27 for(int i=0;i<=len;i++) r[i]=cal[i],cal[i]=0; 28 } 29 int Solve(int n) 30 { 31 for(int i=1;i<=n+2;i++) f[0][i]=1; 32 for(int i=1;i<=n;i++) 33 { 34 for(int j=2;i*(j-1)<=n;j++) 35 { 36 int tmp=0; 37 for(int h=1;h<=i;h++) 38 Add(tmp,1ll*f[h-1][j+1]*f[i-h][j]%mod); 39 f[i][j]=1ll*tmp*pw[j-1]%mod*pp%mod; 40 } 41 f[i][n/i+2]=0; 42 for(int j=n/i+1;j>=2;j--) 43 Add(f[i][j],f[i][j+1]); 44 } 45 // for(int i=0;i<=n;i++,puts("")) 46 // for(int j=0;j<=n;j++) 47 // printf("%d ",f[i][j]); 48 memset(dp,0,sizeof dp),dp[0]=1; 49 for(int i=1;i<=n;i++) 50 { 51 for(int j=1;j<=i;j++) 52 Add(dp[i],1ll*dp[i-j]*f[j-1][2]%mod*pp%mod); 53 Add(dp[i],f[i][2]); 54 } 55 for(int i=0;i<=n;i++) 56 mo[i]=1ll*(mod-f[n-i][2])*pp%mod; mo[++n]=1; 57 // for(int i=0;i<=n;i++) printf("%d ",mo[i]);puts(""); 58 memset(mu,0,sizeof mu),memset(ret,0,sizeof ret); 59 mu[1]=1,ret[0]=1; int ept=m,ans=0; 60 while(ept) 61 { 62 if(ept&1) Polymul(ret,mu,mo,ret,n); 63 Polymul(mu,mu,mo,mu,n),ept>>=1; 64 }//for(int i=0;i<=n;i++) printf("%d ",ret[i]);puts(""); 65 for(int i=0;i<n;i++) 66 Add(ans,1ll*dp[i]*ret[i]%mod); 67 return ans; 68 } 69 int main() 70 { 71 scanf("%d%d%d%d",&m,&k,&x,&y); 72 p=1ll*x*Qpow(y,mod-2)%mod; 73 pp=(1-p+mod)%mod,pw[0]=1; 74 for(int i=1;i<=k;i++) 75 pw[i]=1ll*pw[i-1]*p%mod; 76 printf("%d",(Solve(k)-Solve(k-1)+mod)%mod); 77 return 0; 78 }
SDOI 2016 储能表
居然是数位DP,惊了
$dp[b][0/1][0/1][0/1][2]$表示第$b$位时是否碰到n/m/k的上界......的方案数和异或和
指针看着真难受,可读性--;但是用高维数组又长又慢,就凑活着吧=。=
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 using namespace std; 6 ll T,n,m,k,mod,dp[72][2][2][2][3]; 7 void Add(ll &x,ll y) 8 { 9 x+=y; 10 if(x>=mod) x-=mod; 11 } 12 void i207M() 13 { 14 scanf("%lld%lld%lld%lld",&n,&m,&k,&mod); 15 memset(dp,0,sizeof dp),n--,m--; 16 } 17 void DFS(int bit,int rn,int rm,int rk) 18 { 19 ll *pt=dp[bit][rn][rm][rk]; 20 if(bit==63) *pt=1; 21 else 22 { 23 if(*(pt+2)) return; 24 int bt=62-bit,np=(n>>bt)&1,mp=(m>>bt)&1,kp=(k>>bt)&1; 25 int lim1=rn?np:1,lim2=rm?mp:1; 26 for(int i=0;i<=lim1;i++) 27 for(int j=0;j<=lim2;j++) 28 if(!rk||((i^j)>=kp)) 29 { 30 int nb=bit+1,nn=rn&&(i==np),nm=rm&&(j==mp),nk=rk&&((i^j)==kp); 31 DFS(nb,nn,nm,nk); ll b=(1ll<<(62-bit))%mod,*pts=dp[nb][nn][nm][nk]; 32 Add(*pt,*pts),Add(*(pt+1),((i^j)*b* *pts%mod+*(pts+1))%mod); 33 } 34 *(pt+2)=true; 35 } 36 return; 37 } 38 int main() 39 { 40 scanf("%lld",&T); 41 while(T--) 42 { 43 i207M(),DFS(1,1,1,1); ll *pt=dp[1][1][1][1]; 44 printf("%lld ",(*(pt+1)-k%mod* *pt%mod+mod)%mod); 45 } 46 return 0; 47 }
滑稽树下滑稽果
咕咕咕
量子态的棋盘
咕咕咕
CF848E
咕咕咕