大水题(water)
Posted D O Time
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大水题(water)相关的知识,希望对你有一定的参考价值。
题目描述
dzy 定义一个 $n^2$ 位的数的生成矩阵 $A$ 为一个大小为 $n \times n$ 且 Aij 为这个数的第 $i \times n+j-n$ 位的矩阵。
现在 dzy 有一个数 $n^2$ 位的数 k,他想知道所有小于等于 k 的数的 $n \times n$ 生成矩阵有多少种。(如果不足 $n^2$ 位则补前缀零)
输入输出格式
输入格式
第一行一个数 $n$,第二行一个 $n^2$ 位的数 $k$
输出格式
仅一行表示答案,答案可能很大,你只需输出答案对 $10^9 + 7$ 取模后的结果。
样例 1
输入1
2
1000
输出1
954
数据范围
对于 $30\%$ 的数据 $n \le 2$
对于 $100\%$ 的数据 $n \le 1000$,且 $n$ 为偶数
提示
如果两个生成矩阵在其中一个旋转 $\color{green}{180}$ 度后可以重叠,则称这两个矩阵是相同的。
题解:
这道题看了就一脸懵逼,大火题被说成了大水题了.........
言归正传:
先和网上一样贴公式:
设$f(i)$为$i$在$n^2$位中翻转后的数。
$$ans=k- \frac{\sum_{i}^{f(i) \in [1,k]}1 - \sum_{i}^{f(i) \in [1,k]}(f(i)==i)}{2}$$就是翻转之后的数的个数减去回文数,再除以2就是重复统计的数了。
设$$f[i][j][k],i \in [1,k],j \in [0,1],k \in [0,1]$$为当前枚举到第i位,前i位是否是严格的小于k的前i位的(是为1否为0),将前i位翻转之后的数是否是严格小于等于k的后i位的。那么答案为:
$$ans=k- \frac{(f[n][1][1]+f[n][0][1])-(f[n/2][1][0]+f[n/2][1][1]+f[n/2][0][1])}{2}$$
我们在枚举i,j,k和数字1~9时,就保证前i为严格小于等于,那么j=1就是严格小于,否则就是等于了。
$$(f[n][1][1]+f[n][0][1])$$是$$\sum_{i}^{f(i) \in [1,k]}1$$。前n位不管是小于还是等于,只要翻转之后也在1~n之间就行了。
$$(f[n/2][1][0]+f[n/2][1][1]+f[n/2][0][1])$$是$$\sum_{i}^{f(i) \in [1,k]}(f(i)==i)$$前n/2位翻转之后把后n/2位给补齐了,正好是一个回文数,那么前n/2位严格小于,自然满足条件,如果只是等于,就要翻转之后也是小于等于的。
1 #include<queue> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define RG register 8 using namespace std; 9 const int mod=1000000007; 10 long long int n,ans,GG,Two=500000004,X,Y,Z; 11 char s[1000099]; 12 int a[1000099],dp[1000099][2][2]; 13 int main() 14 { 15 freopen("water.in","r",stdin); 16 freopen("water.out","w",stdout); 17 cin>>n; 18 n*=n; 19 scanf("%s",s+1); 20 for(int i=1;i<=n;i++) 21 { 22 a[i]=s[i]-‘0‘; 23 GG=GG*10+a[i]; 24 GG%=mod; 25 } 26 dp[0][0][1]=1; 27 for(RG int i=0;i<n;i++) 28 for(RG int j=0;j<=1;j++) 29 for(RG int k=0;k<=1;k++) 30 if(dp[i][j][k]!=0)//加速(没卵用) 31 for(RG int l=0;l<=9;l++)//枚举i+1位的数字。 32 { 33 if(l<=a[i+1]||j)//这一位要小于等于或者之前已经小于了。 34 { 35 RG bool b=(l<a[i+1])||j;//这里不能取等号,因为j代表的是严格小于才为1。 36 RG bool c=(l==a[n-i]&&k)||(l<a[n-i]);//。。。严格的小于等于,因为n-i是从后往前的如果后面的相等,这以为自然可以相等,否则这以为必须严格小于才行。 37 dp[i+1][b][c]+=dp[i][j][k]; 38 dp[i+1][b][c]%=mod; 39 } 40 else break; 41 } 42 X=(dp[n][0][1]+dp[n][1][1])%mod; 43 Y=(dp[n/2][1][0]+dp[n/2][0][1]+dp[n/2][1][1])%mod; 44 Z=((X-Y)*Two)%mod; 45 ans=(GG-Z+mod)%mod; 46 cout<<ans<<endl; 47 return 0; 48 }
以上是关于大水题(water)的主要内容,如果未能解决你的问题,请参考以下文章
Compote CodeForces - 746A 又是一个大水题~~~~~
PAT甲题题解-1070. Mooncake (25)-排序,大水题
Arpa’s hard exam and Mehrdad’s naive cheat CodeForces - 742A (大水题)