题目大意
1. 题目定义
给定一个长度为 n 的字符串 s(由 0、1、? 组成)和一个正整数 c。
函数 f(w) 的定义:
对于一个仅含 0 和 1 的字符串 w,其值 f(w) 表示满足以下条件的 [0,1,…,n−1] 全排列 p 的总数:
注:MEX(Minimum Excluded)指集合中未出现的最小非负整数。
2. 目标任务
通过将 s 中的所有 ? 替换为 0 或 1 来构造字符串 w。在所有满足 f(w) 不能被 c 整除 的字符串 w 中,计算 f(w) 的最小值。
3. 输出要求
4. 样例解释辅助理解
-
样例 3 (n=4,c=100,s=1001):
字符串固定为 1001。此时 f(1001)=4,满足条件的排列包括 [0,2,3,1],[0,3,2,1],[1,2,3,0],[1,3,2,0]。由于 4 不能被 100 整除,答案为 4。
-
样例 7 (n=5,c=8,s=100?1):
若将 ? 替换为 0 得到 w=10001,经计算 f(w)=12。由于 12 不能被 8 整除,且经比较这是所有可能替换中的最小值,故输出 12。
-
样例 2 (n=3,c=1,s=???):
无论如何替换 ?,任何整数 f(w) 都能被 1 整除。因此不存在满足 “不能被 c 整除” 条件的 w,输出 −1。
CF-1075-D1. Little String (Easy Version)(把序列生成的过程看成不断插入数字的过程)(插入过程可以写为一个循环,应该多少范围就多少范围,特判写在循环里面)
Untitled
思路讲解
那么是这样子的,这道题目如果把这个序列生成的这个过程看成从 0∼n−1 不断插入的过程,那么如果 wi=0,那么 i 就插入在原来 0∼i−1 之间的空当中。wi=1,只能插入在 0∼i−1 的两段。
D1 当中,我们采用如上方法得到答案。
这道题目,其实想让我们求的是在不被 c 整除的前提下,能够得到的最小值。
那其实说白了,想让值比较小,那就除了首位,结尾,全部填 1 就完了(遇到 ?),不过现在就是这个不能被 c 整除比较烦。
当然,除了首位,当 i−1 为偶数的时候,也应该填写这个 ‘1’,因为反正都要引入 2,那不如就引入一个 2。
不过这道题目,其实就是一个分类讨论:
对于非 2 的幂次,不额外引入任何奇数素因子,总是最好的。因此,采用这个我们之前说的策略:
那就除了首位,结尾,全部填 1 就完了(遇到 ?时)
那么对于 2 的幂次,先不断填 2 进去,发现不行了,我们就回退,乘以 i−1,注意逆序遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| for (int i=N-1;i>=1;--i) { if (W[i]=='?') { ll ans_c_backup=ans_c,ans_backup=ans; ans_c*=2; ans_c%=C; ans*=2; ans%=mod; if (ans_c==0) { ans_c=ans_c_backup; ans=ans_backup; ans*=(i-1); ans%=mod; ans_c*=i-1; ans_c%=C; } } }
|
不过是对于什么进行分类讨论呢?
我们上面有一些地方,加上原本的串,都已经确定了一些,把这一部分的值计算出来,我们记作 ans。那么我们知道,ans 与 C 的因子的交集就是 gcd(ans,C)(可以用该式子计算: gcd(ans,C)=gcd(ansmodC,C))。那么 C 当中还没有被消掉的因子的集合就是:
gcd(ans,C)C
我们就是对还未被消掉的因子集合进行分类讨论。
AC代码
AC
https://codeforces.com/contest/2189/submission/360006878
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
#include <bits/stdc++.h> #include <ranges> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using LD = long double;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = (ll)1e9+7; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT;
void Solve() { ull N,C; cin >> N >> C; string W; cin>>W; W.insert(W.begin(),'#'); if (W[1]=='?') { W[1]='1'; } if (W[N]=='?') { W[N]='1'; } if (W[1]!='1' || W[N]!='1') { cout<<-1<<"\n"; return; } if (W[2]=='?') { W[2]='0'; } for (int i=1;i<=N-1;++i) { if (W[i]=='?') { if ((i-1)%2==0) { W[i]='1'; } } } ll ans=1,ans_c=1; for (int i=1;i<=N-1;++i) { if (W[i]=='?') { continue; } if (W[i]=='1') { ans*=2; ans%=mod; ans_c*=2; ans_c%=C; }else { ans*=(i-1); ans%=mod; ans_c*=i-1; ans_c%=C; } } if (ans_c==0) { cout<<-1<<"\n"; return; } ull rem_C=C/gcd(ans_c,(ll)C); if (has_single_bit(rem_C)) { for (int i=N-1;i>=1;--i) { if (W[i]=='?') { ll ans_c_backup=ans_c,ans_backup=ans; ans_c*=2; ans_c%=C; ans*=2; ans%=mod; if (ans_c==0) { ans_c=ans_c_backup; ans=ans_backup; ans*=(i-1); ans%=mod; ans_c*=i-1; ans_c%=C; } } } if (ans_c==0) { cout<<-1<<"\n"; return; } cout<<ans<<"\n"; }else { for (int i=1;i<=N-1;++i) { if (W[i]=='?') { ans*=2; ans%=mod; ans_c*=2; ans_c%=C; } } if (ans_c==0) { cout<<-1<<"\n"; return; } cout<<ans<<"\n"; }
}
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> lT; while(lT--) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)