• 20140708总结


    今天的题还是比较水的。。涨自信?

    第一题。。显而易见的dp:dp[i][j][k][l][m]:表示i位,j个1,k是否顶上界,l个前导零,是否仍在前导零上。转移方程比较复杂,详见代码。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 long long dp[50][50][2][50][2];
     6 long long work(long long x)
     7 {
     8     long long top[200];
     9     memset(dp,0,sizeof(dp));
    10     memset(top,0,sizeof(top));
    11     long long i=1;
    12     long long j=1;
    13     if(x==0) return 0;
    14     while(x/j)
    15     {
    16         i++;
    17         j*=2;
    18     }
    19     if(i)
    20         i--;
    21     long long n=i;
    22     while(x)
    23     {
    24         top[i]=x%2;
    25         x/=2;
    26         i--;
    27     }
    28 //    for(int i=1;i<=n;i++)
    29 //        cout<<top[i];
    30 //    cout<<endl<<endl;
    31     dp[1][0][1][0][0]=1;
    32 //    for(int i=1;i<=n;i++)
    33 //        cout<<top[i];
    34 //    cout<<endl;
    35     for(i=1;i<=n;i++)
    36         for(j=0;j<=n/2;j++)
    37             for(int k=0;k<=n;k++)
    38             {
    39                 dp[i+1][j][0][k+1][0]+=dp[i][j][0][k][0];
    40                 dp[i+1][j+1][0][k][1]+=dp[i][j][0][k][0];
    41                 if(top[i]==0)
    42                     dp[i+1][j][1][k+1][0]+=dp[i][j][1][k][0];
    43                 else
    44                 {
    45                     dp[i+1][j][0][k+1][0]+=dp[i][j][1][k][0];
    46                     dp[i+1][j+1][1][k][1]+=dp[i][j][1][k][0];
    47                 }
    48                 for(long long l=0;l<=1;l++)
    49                     dp[i+1][j+l][0][k][1]+=dp[i][j][0][k][1];
    50                 for(long long l=0;l<=top[i];l++)
    51                     dp[i+1][j+l][l==top[i]][k][1]+=dp[i][j][1][k][1];
    52 //                cout<<dp[i][j][up]<<endl;
    53             }
    54     long long ans=0;
    55     for(int k=0;k<=n;k++)
    56         for(int i=1;i<=(n-k)/2;i++)
    57         {
    58             ans+=dp[n+1][i][0][k][1]+dp[n+1][i][1][k][1];
    59         }
    60     
    61 //    for(int j=1;j<=n+1;j++)
    62 //    for(int k=0;k<=n;k++)
    63 //    for(int i=1;i<=n;i++)
    64 //        cout<<dp[j][i][0][k][1];
    65     return ans;
    66 }
    67 void work()
    68 {
    69     freopen("testA.in","r",stdin);
    70     freopen("testA.out","w",stdout);
    71     long long L,R;
    72     cin>>L>>R;
    73     if(L==1)
    74         cout<<work(R)<<endl;
    75     else
    76         cout<<work(R)-work(L-1)<<endl;
    77 //    cout<<work(R)<<"  "<<work(L-1)<<endl;
    78 }
    79 int main()
    80 {
    81     work();
    82     return 0;
    83 }
    View Code

     第二题比较复杂,大意就是把[ai,bi] 作为区间,落在[1,N]上,互不重叠,长度互不相等。然后dp[j][k]表示在i位,选了k个,其和为j。

    然后答案就是,详见标程代码(我还没有写出来)。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 using namespace std;
     6 const long long MOD =1000000007LL;
     7 long long dp[1007][1007];
     8 long long C[2014][2014];
     9 long long x[101];
    10 #ifdef unix
    11 #define LL "%lld
    "
    12 #else 
    13 #define LL "I64d
    "
    14 #endif
    15 void init()
    16 {
    17     memset(dp,0,sizeof(dp));
    18     memset(C,0,sizeof(C));
    19     memset(x,0,sizeof(x));
    20     x[0]=1;
    21     for(int i=1;i<=100;i++)
    22         x[i]=x[i-1]*i%MOD;
    23     for(int i=1;i<1000;i++)
    24     {
    25         C[i][i]=1;
    26         C[i][0]=1;
    27         for(int j=1;j<i;j++)
    28         {
    29             C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
    30         }
    31     }
    32     dp[0][0]=1;
    33     for(int i=1;i<=1000;i++)    
    34         for(int j=1000;j>=i;j--)
    35             for(int k=50;k>0;k--)
    36                 dp[k][j]=(dp[k][j]+dp[k-1][j-i])%MOD;
    37 }
    38 int main()
    39 {
    40     init();
    41     int T,N,K;
    42     cin>>T;
    43     long long ans=0;
    44     while(T--)
    45     {
    46         cin>>N>>K;
    47         if(K*(K+1)/2>N)
    48         {
    49             printf("0
    ");
    50             continue;
    51         }
    52         ans=0;
    53         for(int L=K;L<=N;L++)
    54         {
    55             ans=(ans+dp[K][L]*C[N+K-L][K]%MOD)%MOD;
    56         }
    57         printf("%lld
    ",(ans*x[K])%MOD);
    58     }
    59 }
    View Code

    第三题比较水,我就不多说什么了,多特判就好了。。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int main()
     5 {
     6     freopen("testC.in","r",stdin);
     7     freopen("testC.out","w",stdout);
     8     int n,m,x;
     9     cin>>n>>m>>x;
    10     if(x<0)
    11     {
    12         cout<<0<<endl;
    13         return 0;
    14     }
    15     if(x==0)
    16     {
    17         cout<<n*m/2<<endl;
    18         return 0;
    19     }
    20     x-=1;
    21     n-=2*x;
    22     m-=2*x;
    23     if(n<=0||m<=0)
    24         cout<<0<<endl;
    25     else if(n==1||m==1)
    26         cout<<n*m-n*m/2<<endl;
    27     else
    28         cout<<(n+m)-2<<endl;
    29     return 0;
    30 }
    View Code
  • 相关阅读:
    现代程序设计——homework-01
    数据结构 学习笔记03——栈与队列
    MCI 函数与命令
    mciSendString用法
    VC6.0 error LNK2001: unresolved external symbol _main解决办法
    数据结构 学习笔记02——线性表
    数据结构 学习笔记01
    《windows程序设计》学习_4:文本输出,加滚动条
    浅析指针(pointer)与引用(reference)
    指针数组 | 数组指针
  • 原文地址:https://www.cnblogs.com/JackSlowFuck/p/3831941.html
Copyright © 2020-2023  润新知