• 八校联考第一场第二试 大水题


    【题意】

      dzy 定义一个n^2 位的数的生成矩阵A 为一个大小为n*n 且Aij 为这个数的第i*n+j-n位的矩阵。

      现在dzy 有一个数n^2 位的数k,他想知道所有小于等于k 的数的n*n 生成矩阵有多少种。(如果不足n^2 位则补前缀零)
      如果两个生成矩阵在其中一个旋转180 度后可以重叠,则称这两个矩阵是相同的。
      n为小于等于1000的正偶整数。
    【题解】
      以前的模拟题今天被虐了。。。。好久没写博了更一下吧。。
      实际上直接可以当作一个n*n位的整数处理。
      设F(I)为i翻转后的数。
        答案可以分为3部分求:
        一是小于等于k的数的个数(设为S1)。
        二是小于等于k且翻转后的数也小于等于k的数个数(设为S2)。
        三是小于等于k且等于自身翻转的数的个数(设为S3)。
        于是$Ans=k-\frac{\sum_{i=1}^{k}[f[i]\in (1,k)]-\sum_{i=1}^{k}[f[i]==i]}{2}=S1-(S2-S3)/2$
        这三部分可以用数位dp求出:
        设x为
        dp[i][j][p]表示枚举的整数在
        1.当前处理到第i位(这一维可以滚动的);
        2.j为一个01变量,标记创造的整数前一段长度为i的部分是小于还是等于k的前一部分;
        3.p也是一个01变量,表示这一段数翻转后小于等于还是大于原数的后一部分;
        状态下的合法个数。
        状态转移方程比较麻烦,细节比较多吧,注意一下各个状态之间的关系就行了,所以具体不多说了(好吧我比较懒。。)
        于是  S1=k
            S2=dp[n][0][0]+dp[n][1][0]
            S3=dp[n/2][0][0]+dp[n/2][0][1]+dp[n/2][1][0]
        最后代入原式即可求得答案。
    【代码】
     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <iostream>
     4 #define ll long long
     5 #define mo 1000000007
     6 using namespace std;
     7 char str[1001000];
     8 int n,s1,s2,s3,s,dp[1000100][2][2],a[1000100];
     9 int main()
    10 {
    11     cin>>n;
    12     scanf("%s",str+1);
    13     n=n*n;
    14     for (int i=1;i<=n;++i)
    15         a[i]=str[i]-48;
    16     dp[0][1][0]=1;
    17     for (int i=0;i<n;++i)
    18         for (int j=0;j<2;++j)
    19             for (int k=0;k<2;++k)
    20             {
    21                 if (j==0)    s1=10; else s1=a[i+1];
    22                 if (k==0)    s2=a[n-i]+1; else s2=a[n-i];
    23                 dp[i+1][0][0]=(dp[i+1][0][0]+(ll)dp[i][j][k]*min(s1,s2)%mo)%mo;
    24                 if (j==1 && s2>a[i+1])    dp[i+1][1][0]=(dp[i][j][k]+dp[i+1][1][0])%mo;
    25                 dp[i+1][0][1]=(dp[i+1][0][1]+(ll)dp[i][j][k]*max(0,s1-s2)%mo)%mo;
    26                 if (j==1 && s2<=a[i+1])    dp[i+1][1][1]=(dp[i+1][1][1]+dp[i][j][k])%mo;
    27             }    
    28     s1=((dp[n][0][0]+dp[n][0][1])%mo+(dp[n][1][0]+dp[n][1][1])%mo)%mo;
    29     s2=(dp[n][0][0]+dp[n][1][0])%mo;
    30     s3=((dp[n/2][0][0]+dp[n/2][1][0])%mo+dp[n/2][0][1])%mo;    
    31     s=s1-(ll)(s2-s3)*((mo+1)/2)%mo-1;
    32     cout<<(s%mo+mo)%mo<<endl;
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    No necessary symbol fonts
    apt-get Error BrokenCount
    Repository XXX does not have a Realease file
    网页报错:You don't have permission to access
    Operating System not found
    JAVA平台AOP技术研究
    AOP技术基础
    SpringAOP浅析
    CGLIB动态代理
    Java设计模式—Proxy动态代理模式
  • 原文地址:https://www.cnblogs.com/Bleacher/p/7147732.html
Copyright © 2020-2023  润新知