Zero Escape
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 56 Accepted Submission(s): 18
Problem Description
Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikoshi (you may hear about ever17?) and developed by Chunsoft.
Stilwell is enjoying the first chapter of this series, and in this chapter digital root is an important factor.
This is the definition of digital root on Wikipedia:
The digital root of a non-negative integer is the single digit value obtained by an iterative process of summing digits, on each iteration using the result from the previous iteration to compute a digit sum. The process continues until a single-digit number is reached.
For example, the digital root of 65536 is 7 , because 6+5+5+3+6=25 and 2+5=7 .
In the game, every player has a special identifier. Maybe two players have the same identifier, but they are different players. If a group of players want to get into a door numbered X(1≤X≤9) , the digital root of their identifier sum must be X .
For example, players {1,2,6} can get into the door 9 , but players {2,3,3} can't.
There is two doors, numbered A and B . Maybe A=B , but they are two different door.
And there is n players, everyone must get into one of these two doors. Some players will get into the door A , and others will get into the door B .
For example:
players are {1,2,6} , A=9 , B=1
There is only one way to distribute the players: all players get into the door 9 . Because there is no player to get into the door 1 , the digital root limit of this door will be ignored.
Given the identifier of every player, please calculate how many kinds of methods are there, mod 258280327 .
Stilwell is enjoying the first chapter of this series, and in this chapter digital root is an important factor.
This is the definition of digital root on Wikipedia:
The digital root of a non-negative integer is the single digit value obtained by an iterative process of summing digits, on each iteration using the result from the previous iteration to compute a digit sum. The process continues until a single-digit number is reached.
For example, the digital root of 65536 is 7 , because 6+5+5+3+6=25 and 2+5=7 .
In the game, every player has a special identifier. Maybe two players have the same identifier, but they are different players. If a group of players want to get into a door numbered X(1≤X≤9) , the digital root of their identifier sum must be X .
For example, players {1,2,6} can get into the door 9 , but players {2,3,3} can't.
There is two doors, numbered A and B . Maybe A=B , but they are two different door.
And there is n players, everyone must get into one of these two doors. Some players will get into the door A , and others will get into the door B .
For example:
players are {1,2,6} , A=9 , B=1
There is only one way to distribute the players: all players get into the door 9 . Because there is no player to get into the door 1 , the digital root limit of this door will be ignored.
Given the identifier of every player, please calculate how many kinds of methods are there, mod 258280327 .
Input
The first line of the input contains a single number
T
, the number of test cases.
For each test case, the first line contains three integers n , A and B .
Next line contains n integers idi , describing the identifier of every player.
T≤100 , n≤105 , ∑n≤106 , 1≤A,B,idi≤9
For each test case, the first line contains three integers n , A and B .
Next line contains n integers idi , describing the identifier of every player.
T≤100 , n≤105 , ∑n≤106 , 1≤A,B,idi≤9
Output
For each test case, output a single integer in a single line, the number of ways that these
n
players can get into these two doors.
Sample Input
4 3 9 1 1 2 6 3 9 1 2 3 3 5 2 3 1 1 1 1 1 9 9 9 1 2 3 4 5 6 7 8 9
Sample Output
1 0 10 60
把N个数分成两组,一组加起来是A,一组加起来是B,1<=A,B<=9,也可以全分到同一组。其中加是按照他给的规则加,就是一位一位加,超过一位数了再拆分成一位一位加。
因为把N个数全加起来再按照那个规则处理和两个两个加是一样的,用dp[i][j][k]表示前i个数分两组,第一组和为j,第二组和为k有多少种,直接根据a[i]和dp[i-1]的情况递推就行了(如果当前和为j,这一位是a[i],若j>a[i],上一位要取的是j-a[i],否则上一位是9-(a[i]-j),虽然和一般加法不一样,但也差不了多少)。这里N很大,用滚动数组。但我一开始交上去超时,然后发现j和k不需要两重循环,因为前i个数的和是确定的,那么如果j确定了,k也确定了,所以可以先预处理前缀和(按他这种加法规则的和),每次根据j直接算出k。这里特别要注意j,k等于0的情况,进行特殊处理。
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long LL;
const int MAXN=100010;
const LL MOD= 258280327;
int T,N,A,B;
int a[MAXN],sum[MAXN];
LL dp[2][10][10];
int cal(int i,int j){
if(j>i) return j-i;
return 9-(i-j);
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&N,&A,&B);
memset(dp,0,sizeof(dp));
sum[0]=0;
for(int i=1;i<=N;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
if(sum[i]>=10) sum[i]-=9;
}
int cur=0;
dp[cur][a[1]][0]=1;
dp[cur][0][a[1]]=1;
for(int i=2;i<=N;i++){
cur=!cur;
memset(dp[cur],0,sizeof(dp[cur]));
for(int j=0;j<=9;j++){
int k;
if(j==0) k=sum[i];
else k=cal(j,sum[i]);
if(j==a[i]) dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][0][k])%MOD;
if(k==a[i]) dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][j][0])%MOD;
if(j>0){
int t=cal(a[i],j);
dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][t][k])%MOD;
}
if(k>0){
int t=cal(a[i],k);
dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][j][t])%MOD;
}
//j==sum[i]时k可能为0
if(j==sum[i]){
k=0;
if(j==a[i]) dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][0][k])%MOD;
if(k==a[i]) dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][j][0])%MOD;
if(j>0){
int t=cal(a[i],j);
dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][t][k])%MOD;
}
if(k>0){
int t=cal(a[i],k);
dp[cur][j][k]=(dp[cur][j][k]+dp[!cur][j][t])%MOD;
}
}
}
}
LL ans=(dp[cur][A][0]+dp[cur][0][B]+dp[cur][A][B])%MOD;
printf("%I64d\n",ans);
}
return 0;
}