[bzoj1361][Wc2004]孿生項鍊【dp】【字串】【容斥原理】
阿新 • • 發佈:2019-01-06
那麼答案就是
記得要用高精度。
第一問:我們可以先把給定的串倍長到,然後在末位+1,進位,並去掉末尾的0,這樣子一定得到比它大的最小串。
現在我們來證明這是對的,首先最小是肯定的,那麼接下來就是是否迴圈同構了。考慮反證法,如果迴圈同構,那麼後面的那一段在之前一定比前面的小,所以之前的串並不是最小的字典序表示,與給定的事實相反。
時間複雜度
【程式碼】
/* - - - - - - - - - - - - - - -
User : VanishD
problem : [bzoj1361]
Points :
- - - - - - - - - - - - - - - */
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define M 200010
# define N 1010
using namespace std;
int read(){
int tmp = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9'){ if (ch == '-') fh = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){ tmp = tmp * 10 + ch - '0'; ch = getchar(); }
return tmp * fh;
}
struct INT{
int len, num[N];
void print(){
for (int i = len; i > 0; i--)
printf("%d", num[i]);
printf("\n");
}
}tnp, f[N], nxt;
INT operator -(INT &a, INT &b){
nxt = a; int i;
for (i = 1; i <= nxt.len; i++) nxt.num[i] -= b.num[i];
for (i = 1; i < nxt.len; i++)
if (nxt.num[i] < 0)
nxt.num[i] += 10, nxt.num[i + 1] -= 1;
while (nxt.num[nxt.len] == 0)
nxt.len--;
return nxt;
}
INT operator *(INT &a, int b){
nxt = a; int i;
for (i = 1; i <= nxt.len; i++) nxt.num[i] *= b;
for (i = 1; i <= nxt.len || nxt.num[i] != 0; i++)
nxt.num[i + 1] += nxt.num[i] / 10, nxt.num[i] %= 10;
nxt.len = i - 1;
return nxt;
}
INT operator /(INT &a, int b){
memset(nxt.num, 0, sizeof(nxt.num));
nxt.len = 0; int i, tmp = 0;
for (i = a.len; i >= 1; i--){
tmp = tmp * 10 + a.num[i];
nxt.num[i] = tmp / b;
nxt.len = max(nxt.len, (nxt.num[i] > 0) ? i : 0);
tmp %= b;
}
return nxt;
}
char mp[M];
int n, m, k;
int main(){
// freopen("bzoj1361.in", "r", stdin);
// freopen("bzoj1361.out", "w", stdout);
n = read(), m = read(), k = read();
scanf("\n%s", mp + 1);
tnp.len = 1, tnp.num[1] = 1;
for (int i = 1; i <= k; i++){
tnp = tnp * 2;
f[i] = tnp;
for (int j = 1; j < i; j++)
if (i % j == 0) f[i] = f[i] - f[j];
}
f[k] = f[k] / k;
f[k].print();
for (int i = 1; i <= m; i++) mp[i] -= '0';
for (int i = m + 1; i <= n; i++)
mp[i] = mp[(i - 1) % m + 1];
mp[n]++;
int tmp = n;
while (mp[tmp] == 2){
mp[tmp--] = 0;
mp[tmp]++;
}
for (int i = 1; i <= tmp; i++)
printf("%d", mp[i]);
printf("\n");
return 0;
}