QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#880845 | #8330. Count off 3 | juan_123 | WA | 65ms | 97972kb | C++14 | 5.0kb | 2025-02-03 21:28:11 | 2025-02-03 21:28:12 |
Judging History
answer
/*
有一个很显然的做法是考虑 dp
显然我们只关心 base 为 1,2,3,4,5,6 时 mod 7 的余数,全部记录下来得到一个 n \times 7^6 的做法。
这个做法太劣了,这么做主要是为了避免字典序的限制
我们不妨先不考虑字典序的限制,把它当作一个六维的背包去做,发现这个多重背包的计数如果你不 NTT 疑似做不了
启发我们考虑这个 base 的性质,注意到一件事情是 base = k 和 base = 7-k 在偶数位上的值相同,在奇数位上的值相反
所以你可以对偶数的奇数依次做三维的背包然后合并,合并的时候枚举偶数的那三维,对奇数的限制是每一维有两个数不能选,对它容斥。
接下来我们考虑字典序,
更进一步的发现上面的那个东西支持我们动态的加数。
可以直接枚举一个 lcp,然后做上面的过程。
所以时间复杂度是 $O(n \times 18^3)$ 的,看上去过不了但是能过。
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1000000007;
const int N = 10000;
int pw[10005][7];
int dp[10005][7][7][7];//偶数
int f[10005][7][7][7];
int pre[10005][8][8][8];
int n;
string ss;
char s[10005];
void init(){
for(int j =1;j<=6;j++){
pw[0][j] = 1;
for(int i = 1;i<=N;i++)pw[i][j] = (pw[i-1][j]*j)%7;
}
//偶数位第一个数必须是 1
int pro1 = 1,pro2 = 2,pro3 = 3;
dp[0][0][0][0] = f[0][0][0][0] = 1;
dp[1][1][1][1] = 1;f[1][0][0][0] = 1;f[1][1][2][3] = 1;
for(int i = 1;i<=N;i++){
int n = i;
pro2 = pro2*2%7,pro3 = pro3*3%7;
for(int j = 0;j<7;j++){
for(int k =0;k<7;k++){
for(int l =0;l<7;l++){
dp[i+1][j][k][l] = (dp[i+1][j][k][l]+dp[i][j][k][l])%mod;
dp[i+1][(j+1)%7][(k+pro2)%7][(l+pro3)%7] = (dp[i+1][(j+1)%7][(k+pro2)%7][(l+pro3)%7]+dp[i][j][k][l])%mod;
}
}
}
pro2 = pro2*2%7,pro3 = pro3*3%7;
for(int j =0;j<7;j++){
for(int k =0;k<7;k++){
for(int l =0;l<7;l++){
// if(f[i][j][k][l]){cout << i << " " << j << " " << k << " " << l << " " << f[i][j][k][l] << endl;}
f[i+1][j][k][l] = (f[i+1][j][k][l]+f[i][j][k][l])%mod;
f[i+1][(j+1)%7][(k+pro2)%7][(l+pro3)%7] = (f[i+1][(j+1)%7][(k+pro2)%7][(l+pro3)%7]+f[i][j][k][l])%mod;
}
}
}
}
for(int i = 0;i<=N;i++){
int n = i;
int sum = 0;
for(int i =0;i<7;i++)for(int j =0;j<7;j++){
int sum1 =0,sum2 = 0,sum3 = 0;
for(int k =0;k<7;k++){
sum = (sum+f[n][i][j][k])%mod;
sum1 = (sum1+f[n][k][i][j])%mod;
sum2 = (sum2+f[n][i][k][j])%mod;
sum3 = (sum3+f[n][i][j][k])%mod;
}
pre[n][7][i][j] = sum1,pre[n][i][7][j] = sum2,pre[n][i][j][7] = sum3;
}
for(int i =0;i<7;i++)for(int j =0;j<7;j++)for(int k = 0;k<7;k++)pre[n][i][j][k] = mod-f[n][i][j][k];
pre[n][7][7][7] = sum;
for(int j = 0;j<7;j++){
int sum1 =0,sum2 =0,sum3 = 0;
for(int k =0;k<7;k++){
for(int l =0;l<7;l++){
sum1 = (sum1+f[n][j][k][l])%mod;
sum2 = (sum2+f[n][k][j][l])%mod;
sum3 = (sum3+f[n][k][l][j])%mod;
}
}
pre[n][j][7][7] = (mod-sum1);
pre[n][7][j][7] = (mod-sum2);
pre[n][7][7][j] = (mod-sum3);
}
}
}
void solve(){
cin >> ss;n = ss.size();
for(int i = 1;i<=n;i++)s[i] = ss[i-1];
int sum[10];memset(sum,0,sizeof(sum));
int ans = 0;
for(int i = 1;i<n;i++){
if(s[i]=='0')continue;
int c = n-i;
int c1 = c/2,c2 = c-c1;
// cout << c1 << " " << c2 << endl;
vector<int>p1[10],p2[10],p3[10];
for(int j =0;j<7;j++){
p1[j].push_back(7);
p1[j].push_back((7-(j+sum[1])%7)%7);// 1
p1[j].push_back((j+sum[6])%7);// 4
sort(p1[j].begin(),p1[j].end());p1[j].erase(unique(p1[j].begin(),p1[j].end()),p1[j].end());
}
for(int k =0;k<7;k++){
p2[k].push_back(7);
p2[k].push_back((7-(k+sum[2])%7)%7);
p2[k].push_back((k+sum[5])%7);
sort(p2[k].begin(),p2[k].end());p2[k].erase(unique(p2[k].begin(),p2[k].end()),p2[k].end());
}
for(int l =0;l<7;l++){
p3[l].push_back(7);
p3[l].push_back((7-(l+sum[3])%7)%7);
p3[l].push_back((l+sum[4])%7);
sort(p3[l].begin(),p3[l].end());p3[l].erase(unique(p3[l].begin(),p3[l].end()),p3[l].end());
}
for(int j =0;j<7;j++){
for(int k = 0;k<7;k++){
for(int l = 0;l<7;l++){
int v1 = dp[c2][j][k][l];
if(!v1)continue;
int tot = 0;
for(auto x:p1[j]){
for(auto y:p2[k]){
for(auto z:p3[l]){
tot += pre[c1][x][y][z];
}
}
}
tot %= mod;
ans = (ans+v1*tot)%mod;
}
}
}
// cout << " " << ans << endl;
// for(int j = 1;j<=6;j++)cout << pw[c][j] << " ";cout << endl;
for(int j = 1;j<=6;j++)sum[j] = (sum[j]+pw[c][j])%7;
}
if(s[n]=='1')for(int j = 1;j<=6;j++)sum[j] = (sum[j]+1)%7;
int ok = (s[n] == '1');for(int j = 1;j<=6;j++)if(!sum[j])ok = 0;
ans = (ans+1)%mod;
// cout << ok << endl;
cout << ans << endl;
}
signed main(){
init();
int t;cin >> t;
while(t--)solve();
return 0;
}/*
1
0
0
0
1
1
1
1
1
101101001000
1
1101
1
110101
1
1000
1
1010
13
5
1
1010
110101
1000111000
101101001000
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 65ms
memory: 97972kb
input:
5 1 1010 110101 1000111000 101101001000
output:
1 3 15 115 515
result:
wrong answer 2nd numbers differ - expected: '2', found: '3'