Mysterious For(hdu4373)

Mysterious For

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 694    Accepted Submission(s): 264

Problem Description

MatRush is an ACMer from ZJUT, and he always love to create some special programs. Here we will talk about one of his recent inventions.

This special program was called "Mysterious For", it was written in C++ language, and contain several simple for-loop instructions as many other programs. As an ACMer, you will often write some for-loop instructions like which is listed below when you are taking an ACM contest.
for (int i = 0; i < n; i++) {
  for (int j = i; j < n; j++) {
    for (int k = j; k < n; k++) {
      blahblahblah();
    }
  }
}

Now, MatRush has designed m for-loop instructions in the "Mysterious For" program, and each for-loop variable was stored in an array a[], whose length is m.

The variable i represents a for-loop instructions is the i-th instruction of the "Mysterious For" program.There only two type of for-loop instructions will occur in MatRush‘s "Mysterious For" program:

1-type: if a for-loop belongs to 1-type, it will be an instruction like this:
for (int a[i] = 0; a[i] < n; a[i]++) {
    ...
}

2-type: if a for-loop belongs to 2-type, it will be an instruction like this:
for (int a[i] = a[i - 1]; a[i] < n; a[i]++) {
    ...
}

In addition, after the deepest for-loop instruction there will be a function called HopeYouCanACIt(), here is what‘s inside:
void HopeYouCanACIt() {
    puts("Bazinga!");
}

So, the "Mysterious For" program, obviously, will only print some line of the saying: "Bazinga!", as it designed for.

For example, we can assume that n equals to 3, and if the program has three 1-type for-loop instructions, then it will run 33=27 times of the function HopeYouCanACIt(), so you will get 27 "Bazinga!" in total. But if the program has one 1-type for-loop instruction followed by two 2-type for-loop instructions, then it will run 3+2+1+2+1+1=10 times of that function, so there will be 10 "Bazinga!" on the screen.

Now MatRush has the loop length n and m loop instructions with certain type, then he want to know how many "Bazinga!" will appear on the screen, can you help him? The answer is too big sometimes, so you just only to tell him the answer mod his QQ number:364875103.

All for-loop instructions are surely nested. Besides, MatRush guaranteed that the first one belongs to the 1-type. That is to say, you can make sure that this program is always valid and finite. There are at most 15 1-type for-loop instructions in each program.

Input

First, there is an integer T(T<=50), the number of test cases.
For every case, there are 2 lines.
The first line is two integer n(1<=n<=1000000) and m(1<=m<=100000) as described above.
The second line first comes an integer k(1<=k<=15), represents the number of 1-type loop instructions, then follows k distinctive numbers, each number is the i-th 1-type loop instruction‘s index(started from 0), you can assume the first one of this k numbers is 0 and all numbers are ascending.
All none 1-type loop instructions of these m one belongs to 2-type.

Output

For each certain "Mysterious For" program, output one line, "Case #T: ans", where T stands for the case number started with 1, and ans is the number of "Bazinga!" mod 364875103.

Sample Input

5
3 3
3 0 1 2
3 3
1 0
3 3
2 0 2
4 4
4 0 1 2 3
10 10
10 0 1 2 3 4 5 6 7 8 9

Sample Output

Case #1: 27
Case #2: 10
Case #3: 18
Case #4: 256
Case #5: 148372219

Hint

For the third program, the code is like this:
for (int a[0] = 0; a[0] < n; a[0]++) {
for (int a[1] = a[0]; a[1] < n; a[1]++) {
for (int a[2] = 0; a[2] < n; a[2]++) {
HopeYouCanACIt();
}
}
}
Because n = 3, the answer is 3*3+2*3+1*3=18.

题意:
m个for循环嵌套,有两种形式,第一类从1开始到n,第二类从上一层循环当前数开始到n,第一层一定是第一种类型,问总的循环的次数对364875103取余的结果。

思路:中国剩余定理+lucas定理;

下面我转载一篇写得不错的思路的一部分

{首先可以看出,每一个第一类循环都是一个新的开始,与前面的状态无关,所以可以把m个嵌套分为几个不同的部分,每一个部分由第一类循环开始,最终结果相乘就可以。
剩下的就是第二类循环的问题,假设一个m层循环,最大到n,
只有第一层:循环n次。C(n, 1)
只有前两层:循环n + (n - 1) + ... + 1 = (n + 1) * n / 2 = C(n + 1, 2);}

接下来是我自己的证明:

有m层循环,然后每层n个;

我们考虑最后一层,然后我们可以用dp的思想,最后一层的第一个数的次数为,C(m-1,m-1),第二个数可以接在上一层,以小于等于第二个结尾的数的后面,那么就是C(m,m-1),同理可以得到剩下的数被计数的个数为C(m+k-1,m-1);

那么这个总的循环次数就是C(m-1,m-1)+C(m,m-1)+C(m+1,m-1)....+C(m+k-1,m-1)+...C(m+n-2,m-1)=

C(m)(m)+C(m,m-1)+C(m+1,m-1)+....C(m+n-2,m-1)根据杨辉三角合并就可得到最终的答案为C(n+m-1,m);

要完整的证明还要用数学归纳法;

然后,我们发现mod不是素数,我们拆分成97*(mod/97);两个素数分别取模,然后用中国剩余定理求出对于mod的模数,同时组合数对97取模用lucas定理,对另一个比较大的直接费马小定理即可。

我的代码G++WA,C++AC不过思路是对的

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <map>
  8 #include <queue>
  9 #include <vector>
 10 using namespace std;
 11 typedef  long long LL;
 12 LL  ak[20];
 13 const LL mod1=97 ;
 14 const LL mod2=3761599;
 15 pair<LL,LL> CHA(LL *a,LL n,LL *b);
 16 LL quick(LL n,LL m,LL p);
 17 LL mod3=364875103;
 18 LL N1[2000000];
 19 LL N2[2000000];
 20 bool flag[100005];
 21 LL lucas(LL n,LL m,LL p);
 22 int main(void)
 23 {
 24         LL i,j,k;
 25         LL n,m;
 26         int __ca=0;
 27         N1[0]=1;
 28         N1[1]=1;
 29         N2[0]=1;
 30         N2[1]=1;
 31         for(i=2; i<=2000000; i++)
 32         {
 33                 N1[i]=(N1[i-1]*i)%mod1;
 34                 N2[i]=(N2[i-1]*i)%mod2;
 35         }
 36         scanf("%lld",&k);
 37         while(k--)
 38         {
 39                 memset(flag,0,sizeof(flag));
 40                 scanf("%lld %lld",&n,&m);
 41                 int nn;
 42                 LL dd;
 43                 scanf("%lld",&dd);
 44                 for(i=0; i<dd; i++)
 45                 {
 46                         scanf("%lld",&ak[i]);
 47                         flag[ak[i]]=true;
 48                 }
 49                 LL ack=1;
 50                 LL alk=1;
 51                 LL cp=1;
 52                 for(i=0; i<m;)
 53                 {
 54                         if(flag[i]&&(flag[i+1]&&i!=m-1||i==m-1))
 55                         {
 56                                 alk=alk*n%mod1;
 57                                 ack=ack*n%mod2;
 58                                 cp=cp*n%mod3;
 59                                 i++;
 60                         }
 61                         else
 62                         {
 63                                 for(j=i+1; j<m; j++)
 64                                 {
 65                                         if(flag[j])
 66                                                 break;
 67                                 }
 68                                 LL cc=j-i;
 69                                 i=j;
 70                                 LL x=N2[n+cc-1];
 71                                 LL y=N2[cc]*N2[n-1];
 72                                 x=x*quick(y,mod2-2,mod2)%mod2;
 73                                 LL ap=lucas(cc,n+cc-1,mod1);
 74                                 alk=alk%mod1*ap%mod1;
 75                                 ack=ack%mod2*(x)%mod2;
 76                         }
 77                 }
 78                 LL aa[10];
 79                 LL bb[10];
 80                 bb[0]=alk;
 81                 bb[1]=ack;
 82                 aa[0]=mod1;
 83                 aa[1]=mod2;
 84                 pair<LL,LL>ANS=CHA(aa,2,bb);
 85                 printf("Case #%d: %lld\n",++__ca,ANS.first%mod3);
 86         }
 87         return 0;
 88 }
 89 LL quick(LL n,LL m,LL p)
 90 {
 91         n%=p;
 92         LL ak=1;
 93         while(m)
 94         {
 95                 if(m&1)
 96                 {
 97                         ak=ak*n%p;
 98                 }
 99                 n=n*n%p;
100                 m/=2;
101         }
102         return ak;
103 }
104 pair<LL,LL> CHA(LL *a,LL n,LL *b)
105 {
106         int i,j;
107         LL sum=1;
108         LL answer=0;
109         for(i=0; i<n; i++)
110         {
111                 sum*=a[i];
112         }
113         for(i=0; i<n; i++)
114         {
115                 LL t=sum/a[i];
116                 LL ni=quick(t,a[i]-2,a[i]);
117                 LL ask=ni*b[i]%sum;
118                 ask=ask*t%sum;
119                 answer+=ask;
120                 answer%=sum;
121         }
122         return make_pair(answer,sum);
123 }
124 LL lucas(LL n,LL m,LL p)
125 {
126         if(n==0)
127         {
128                 return 1;
129         }
130         else
131         {
132                 LL nx=n%p;
133                 LL ny=m%p;
134                 if(nx>ny)
135                 {
136                         return 0;
137                        }
138                                else
139                        {
140                                LL x=n/p;
141                                LL y=m/p;
142                                LL xx=N1[ny];
143                                LL yy=N1[ny-nx]*N1[nx]%p;
144                                LL ni=quick(yy,p-2,p);
145                                ni=ni*xx%p;
146                                return ni*lucas(x,y,p);
147                        }
148                        }
149     }
时间: 2024-11-07 12:27:08

Mysterious For(hdu4373)的相关文章

codeforces Gym 100187H H. Mysterious Photos 水题

H. Mysterious Photos Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/H Description Everyone probably heard the rumours about the constellation of Bermuda Triangle: any person who looks to this constellation of th

HDU - 2145 zz&#39;s Mysterious Present (最短路)

题目大意:有一个人,办了一个party,先到的有礼物.如果有多个人同时到达,就去家离得最远的那个,如果还是多个人同时到达,就去那个编号最大的 解题思路:最短路水题... #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; #define N 310 #define INF 0

codeforces4D - Mysterious Present DP

题意:求限定起始位置的二维最长递增子序列. 解题思路:直接DP 解题代码: 1 // File Name: 4d.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月04日 星期一 19时24分49秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque> 10 #incl

Mysterious Light

1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 int main() 5 { 6 ll i,j,k,m,n,x; 7 ll sum; 8 ll a,b; 9 int flag=1; 10 cin>>n>>x; 11 a=x,b=n-x; 12 sum=n; 13 while(flag) 14 { 15 if(a>b) 16 { 17 ll y=a/b; 18 if

[题解]Codeforces Round #519 - D. Mysterious Crime

[题目] D. Mysterious Crime [描述] 有m个n排列,求一共有多少个公共子段. 数据范围:1<=n<=100000,1<=m<=10 [思路] 对于第一个排列来说,如果第k个位置开始往后L长的子段是一个公共的子段,那么从k开始往后数1,2,...,L-1长的子段都是公共的子段:如果第k个位置开始往后L长的子段是一个公共的子段,但第k个位置开始往后L+1长的子段不是一个公共的子段,那么位置k到位置k+L中任一位置j开始往后直到位置k+L的子段都不是公共的子段.这就

攻防世界 reverse Mysterious

Mysterious  BUUCTF-2019 int __stdcall sub_401090(HWND hWnd, int a2, int a3, int a4) { char v5; // [esp+50h] [ebp-310h] CHAR Text[4]; // [esp+154h] [ebp-20Ch] char v7; // [esp+159h] [ebp-207h] __int16 v8; // [esp+255h] [ebp-10Bh] char v9; // [esp+257h

LA 7267 Mysterious Antiques in Sackler Museum (if-else,枚举)

题意:给定四个矩形,要求从中选出三个,能不能拼成一个矩形. 析:说到这个题,我还坑了队友一次,读题读错了,我直接看的样例,以为是四个能不能组成,然后我们三个就拼命想有什么简便方法,后来没办法了,直接暴力. 康神写了6000多B的代码,全是循环和if-else,我们画出五种情况....然而并不是这样, 只要几个if-else就够,因为就3个,两种情况. 代码如下; #pragma comment(linker, "/STACK:1024000000,1024000000") #inclu

【HDOJ】4373 Mysterious For

1. 题目描述有两种不同类型的循环,并给出一个由1.2组成的序列,表示嵌套的循环类型.问这样组着的循环一共需要多少次循环?并将结果模364875103. 2.基本思路显然,每当遇到一个类型1的序列,即可以判定12...2的嵌套循环共多少次,而1类型的循环次数为常亮.因此,将原序列从1分开,并将每个子序列的循环次数相乘即为总的循环次数.1     共循环n次 = C[n][1]12   共循环n*(n+1)/2次 = C[n+1][2]122 共循环n*(n+1)*(n+2)/6次 = C[n+2

Codeforces Beta Round #4 (Div. 2 Only) D. Mysterious Present

最长上升子序列,这种水题还是一眼就能看出来的. 题目大意: 主人公想在一张w*h的明信片外套信封.他有n个信封,每个信封的长宽给出,问最多能套多少层.给出从小到大的顺序. 解题思路: 最长上升子序列,只不过是记忆路径. 下面是代码: #include <set> #include <map> #include <queue> #include <math.h> #include <vector> #include <string> #