• 省选前作业题汇总1


    (部分是)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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    滑稽树下滑稽果

    咕咕咕

    量子态的棋盘

    咕咕咕

    CF848E 

    咕咕咕

  • 相关阅读:
    P4890 Never·island
    P2617 Dynamic Rankings
    P3243 [HNOI2015]菜肴制作
    P4172 [WC2006]水管局长
    P4219 [BJOI2014]大融合
    P5241 序列
    P1501 [国家集训队]Tree II
    无法读取用户配置文件,系统自动建立Temp临时用户
    组件服务 控制台打不开
    打印服务器 功能地址保护错误
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10442454.html
Copyright © 2020-2023  润新知