zoukankan      html  css  js  c++  java
  • [校内训练20_10_23~25]

    1.

    标准的卢卡斯定理加数位dp,主要是算C(n,i)*C(n,2*i)。

    但由于这题的模数是质数,就不需要考虑很多东西,如:是否超过上限了、是否有连续的进位。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long int ll;
     4 const int maxn=1E6+5;
     5 ll ans,n,mod;
     6 ll fac[maxn],inv[maxn];
     7 int tot,a[66];
     8 inline ll qpow(ll x,ll y)
     9 {
    10     ll ans=1,base=x;
    11     while(y)
    12     {
    13         if(y&1)
    14             ans=ans*base%mod;
    15         base=base*base%mod;
    16         y>>=1;
    17     }
    18     return ans;
    19 }
    20 inline ll C(int x,int y)
    21 {
    22     if(x<y||x<0||y<0)
    23         return 0;
    24     return fac[x]*inv[y]%mod*inv[x-y]%mod;
    25 }
    26 inline void init()
    27 {
    28     fac[0]=1;
    29     for(int i=1;i<mod;++i)
    30         fac[i]=fac[i-1]*i%mod;
    31     inv[mod-1]=qpow(fac[mod-1],mod-2);
    32     for(int i=mod-2;i>=0;--i)
    33         inv[i]=inv[i+1]*(i+1)%mod;
    34     ll x=n;
    35     do
    36     {
    37         a[++tot]=x%mod;
    38         x/=mod;
    39     }while(x);
    40     reverse(a+1,a+tot+1);
    41 }
    42 inline ll solve1()
    43 {
    44     return (qpow(3,n)-1)*qpow(2,mod-2)%mod;
    45 }
    46 bool vis[28][2];
    47 ll f[28][2];
    48 ll dfs(int pos,int pre)// limit doesn't matter
    49 {
    50     if(vis[pos][pre])
    51         return f[pos][pre];
    52     vis[pos][pre]=1;
    53     if(pos==tot)
    54         return f[pos][pre]=1;
    55     ll s=0;
    56     if(pre==0)
    57         for(int nxt=0;nxt<=1;++nxt)
    58         {
    59             int up=(mod-1-nxt)/2;
    60             for(int i=0;i<=up;++i)
    61                 if((2*i>=mod)==nxt)
    62                     s=(s+dfs(pos+1,nxt)*C(a[pos+1],(2*i+nxt)%mod)%mod*C((2*i+nxt)%mod,i))%mod;// it is correct even if 2*i plus an offset is equal to mod
    63         }
    64     else
    65         for(int nxt=0;nxt<=1;++nxt)
    66         {
    67             int up=(mod-1-nxt)/2;
    68             for(int i=up+1;i<=mod-1;++i)
    69                 if((2*i>=mod)==nxt)
    70                     s=(s+dfs(pos+1,nxt)*C(a[pos+1],(2*i+nxt)%mod)%mod*C((2*i+nxt)%mod,i))%mod;
    71         }
    72     return f[pos][pre]=s;
    73 }
    74 inline ll solve2()
    75 {
    76     ll s=dfs(0,0)-1;
    77     return s*qpow(2,mod-2)%mod;
    78 //  for(int i=1;2*i<=n;++i)
    79 //      s=(s+C(n,2*i)*C(2*i,i)%mod)%mod;
    80 //  return s*qpow(2,mod-2)%mod;
    81 }
    82 int main()
    83 {
    84     ios::sync_with_stdio(false);
    85     cin>>n>>mod;
    86     init();
    87     ll ans=(solve1()+solve2())%mod;
    88     cout<<((qpow(3,n)-ans-1)%mod+mod)%mod<<endl;
    89     return 0;
    90 }
    View Code

    2.一个数列是好的,当且仅当它第一位是1,并且每次向后移动一位时,前缀max最多增加1。对于每个数字k,求出所有可能的好的数列中它的出现次数的平方的和。n<=5000。

    考虑如何计算一对位置的贡献和单独位置的贡献。构造一个好的数列的过程,类似于在二维平面上要么向右移动一步,要么向右上移动一步。其中向右移动一步共有y坐标种数字,向右上移动一步就是钦定放了数字y+1,可以依次设计dp然后前缀和优化。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long int ll;
     4 const int maxn=5E3+5;
     5 int n,mod;
     6 int f[maxn][maxn],g[maxn][maxn][2];
     7 int sum1[maxn][maxn],sum0[maxn][maxn];
     8 int G[55];
     9 inline void write(int x)
    10 {
    11     int g=0;
    12     do{G[++g]=x%10;x/=10;}while(x);
    13     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar(' ');
    14 }
    15 inline void add(int&x,int y)
    16 {
    17     x=(x+y)%mod;
    18 }
    19 inline int get(int x)
    20 {
    21     int s=0,h=0;
    22     for(int i=1;i<=n;++i)
    23     {
    24         add(s,sum1[i-1][x]);
    25 //      for(int j=x;j<=n;++j)
    26 //          add(s,(ll)f[i-1][j]*g[i][j][1]%mod*2%mod);
    27         add(h,(ll)f[i-1][x-1]*g[i][x][1]%mod);
    28         if(i==n)
    29             break;
    30         add(s,sum0[i-1][x]);
    31 //      for(int j=x;j<=n;++j)
    32 //          add(s,(ll)f[i-1][j]*g[i][j][0]%mod);
    33         add(s,(ll)f[i-1][x-1]*g[i][x][0]%mod);
    34     }
    35     h=h*2%mod;
    36     for(int i=x-1;i<=n;++i)
    37         add(s,f[n-1][i]);
    38     return (s+h)%mod;
    39 }
    40 inline void solve()
    41 {
    42     f[0][0]=1;
    43     for(int i=1;i<=n;++i)
    44         for(int j=1;j<=i;++j)
    45             f[i][j]=(f[i-1][j-1]+(ll)f[i-1][j]*j%mod)%mod;
    46     for(int i=1;i<=n;++i)
    47         g[n][i][0]=1;
    48     for(int i=n;i>1;--i)
    49         for(int j=1;j<=i;++j)
    50         {
    51             add(g[i-1][j][0],(ll)g[i][j][0]*j%mod);
    52             add(g[i-1][j][1],g[i][j][0]);
    53             add(g[i-1][j][1],(ll)g[i][j][1]*j%mod);
    54              
    55             add(g[i-1][j-1][0],g[i][j][0]);
    56             add(g[i-1][j-1][1],g[i][j][1]);
    57         }
    58     for(int i=1;i<=n;++i)
    59         for(int j=i;j>=1;--j)
    60             add(sum1[i][j],sum1[i][j+1]+(ll)f[i][j]*g[i+1][j][1]%mod*2%mod);
    61     for(int i=1;i<=n;++i)
    62         for(int j=i;j>=1;--j)
    63             add(sum0[i-1][j],sum0[i-1][j+1]+(ll)f[i-1][j]*g[i][j][0]%mod);
    64     for(int i=1;i<=n;++i)
    65         write(get(i));
    66 }
    67 int main()
    68 {
    69     ios::sync_with_stdio(false);
    70     cin>>n>>mod;
    71     solve();
    72     return 0;
    73 }
    View Code

    3.斜率优化。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long int ll;
     4 typedef long double ld;
     5 const ld inf=1E100;
     6 int n,a[305],b[305];
     7 ll f[2][305][305];
     8 struct pt
     9 {
    10     ld x,y;
    11     int num;
    12     pt(ld a=0,ld b=0,int c=0):x(a),y(b),num(c){}
    13 };
    14 inline ld slope(pt A,pt B)
    15 {
    16     return (A.y-B.y)/(A.x-B.x);
    17 }
    18 struct AF
    19 {
    20     pt p[305];
    21     int head,tail;
    22     AF()
    23     {
    24         head=1,tail=0;
    25     }
    26     void clear()
    27     {
    28         head=1,tail=0;
    29     }
    30     inline void add(pt A)
    31     {
    32         while(head<tail&&slope(p[tail-1],p[tail])>=slope(p[tail],A))
    33             --tail;
    34         p[++tail]=A;
    35     }
    36     inline int ask(ld k)
    37     {
    38         if(head>tail)
    39             return -1;
    40         while(head<tail&&slope(p[head],p[head+1])<k)
    41             ++head;
    42         return p[head].num;
    43     }
    44 }Q[305];
    45 inline ll s(ll x)
    46 {
    47     return x*x;
    48 }
    49 inline void solve()
    50 {
    51     for(int i=0;i<2;++i)
    52         for(int j=0;j<=300;++j)
    53             for(int k=0;k<=300;++k)
    54                 f[i][j][k]=(ll)1000000000000;
    55     f[0][0][0]=0;
    56     for(int i=1;i<=n;++i)
    57     {
    58         int p1=i&1,p0=(i&1)^1;
    59         for(int j=0;j<=b[i];++j)
    60         {
    61             Q[j].clear();
    62             for(int k=0;k<=b[i];++k)
    63                 f[p1][j][k]=(ll)1000000000000;
    64         }
    65         if(i==1)
    66             for(int k=1;k<=b[i];++k)
    67                 f[p1][k][k]=0;
    68         else
    69             for(int k=1;k<=b[i];++k)
    70                 for(int l=1;l<=b[i-1];++l)
    71                     f[p1][k][k]=min(f[p1][k][k],f[p0][b[i-1]][l]+s(a[i]+k-a[i-1]-l));
    72         for(int j=1;j<=b[i];++j)
    73         {
    74             for(int k=1;k<j;++k)
    75             {
    76                 int x=Q[j-k].ask(2*k);
    77                 if(x!=-1)
    78                     f[p1][j][k]=min(f[p1][j][k],f[p1][j-k][x]+s(k-x));
    79                 Q[j].add(pt(k,f[p1][j][k]+k*k,k));
    80             }
    81             Q[j].add(pt(j,f[p1][j][j]+j*j,j));
    82         }
    83     }
    84     ll ans=(ll)10000000000000;
    85     int p1=n&1;
    86     for(int i=1;i<=b[n];++i)
    87         ans=min(ans,f[p1][b[n]][i]);
    88     cout<<ans<<endl;
    89 }
    90 int main()
    91 {
    92     ios::sync_with_stdio(false);
    93     cin>>n;
    94     for(int i=1;i<=n;++i)
    95         cin>>a[i]>>b[i];
    96     solve();
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    Spring AOP详解 、 JDK动态代理、CGLib动态代理
    mysql 日期 字符串 时间戳转换
    图文:通过sql server 连接mysql
    c# 数据绑定之 DataFormatString 格式
    sql 截取字符串与 截取字符串最长的字符串
    oracle 清除表空间
    sql 遍历结果print和表格形式
    国家与城市的sql
    sql2005 将一列的多行内容拼接成一行
    oracle和mssql中复制表的比较
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/13898614.html
Copyright © 2011-2022 走看看