[弱校联萌2016]2016弱校联盟十一专场10.5
比赛链接:https://www.bnuoj.com/v3/contest_show.php?cid=8506#info
I.裸数位dp,dp[l][pre][dir][fz]表示长度为l的时候上一个数是pre,此时是统计dir(分为增、减、相同),fz记录当前是否是前导零。有种情况,就是各位相同的情况,要减掉。
ps:其实不用fz这一维,删掉就行了,智障了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 22; 6 // l, pre, dir, fz 7 int dp[maxn][11][3][2]; 8 int digit[maxn]; 9 LL l, r; 10 11 LL dfs(int l, int pre, int dir, bool fz, bool flag) { 12 if(l == 0) return 1; 13 if(!flag && ~dp[l][pre][dir][fz]) return dp[l][pre][dir][fz]; 14 LL ret = 0; 15 int pos = flag ? digit[l] : 9; 16 for(int i = 0; i <= pos; i++) { 17 if(fz&&(i==0)) ret += dfs(l-1,pre,dir,fz,flag&&(i==pos)); 18 else { 19 if(dir==1) { 20 if(i>=pre) ret += dfs(l-1,i,dir,fz&&(i==0),flag&&(i==pos)); 21 } 22 else if(dir == 0) { 23 if(i<=pre) ret += dfs(l-1,i,dir,fz&&(i==0),flag&&(i==pos)); 24 } 25 else if(dir == 2) { 26 if(i==pre||(pre==10&&i)) ret += dfs(l-1,i,dir,fz&&(i==0),flag&&(i==pos)); 27 } 28 } 29 } 30 if(!flag) dp[l][pre][dir][fz] = ret; 31 return ret; 32 } 33 34 LL f(LL x) { 35 int pos = 0; 36 while(x) { 37 digit[++pos] = x % 10; 38 x /= 10; 39 } 40 return dfs(pos,10,0,true,true)+dfs(pos,0,1,true,true)-dfs(pos,10,2,true,true); 41 } 42 43 inline bool scan_d(LL &num) { 44 char in;bool IsN=false; 45 in=getchar(); 46 if(in==EOF) return false; 47 while(in!='-'&&(in<'0'||in>'9')) in=getchar(); 48 if(in=='-'){ IsN=true;num=0;} 49 else num=in-'0'; 50 while(in=getchar(),in>='0'&&in<='9'){ 51 num*=10,num+=in-'0'; 52 } 53 if(IsN) num=-num; 54 return true; 55 } 56 57 int main() { 58 // freopen("in", "r", stdin); 59 memset(dp, -1, sizeof(dp)); 60 int T; 61 scanf("%d", &T); 62 while(T--) { 63 scan_d(l); scan_d(r); 64 printf("%lld\n", f(r)-f(l-1)); 65 } 66 return 0; 67 }
F.矩阵快速幂就可以,先找斐波那契数列在%20160516下的循环节,求出fib对应下标再求一遍。参考了这个http://blog.csdn.net/tsoi_vergil/article/details/52718426
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 5; 6 const LL mod = 20160519; 7 const LL mod1 = 26880696; 8 int n; 9 10 typedef struct Matrix { 11 LL m[maxn][maxn]; 12 int r; 13 int c; 14 Matrix(){ 15 r = c = 0; 16 memset(m, 0, sizeof(m)); 17 } 18 } Matrix; 19 20 Matrix mul(Matrix m1, Matrix m2, LL mod) { 21 Matrix ans = Matrix(); 22 ans.r = m1.r; 23 ans.c = m2.c; 24 for(int i = 1; i <= m1.r; i++) { 25 for(int j = 1; j <= m2.r; j++) { 26 for(int k = 1; k <= m2.c; k++) { 27 if(m2.m[j][k] == 0) continue; 28 ans.m[i][k] = ((ans.m[i][k] + m1.m[i][j] * m2.m[j][k] % mod) % mod) % mod; 29 } 30 } 31 } 32 return ans; 33 } 34 35 Matrix quickmul(Matrix m, int n, LL mod) { 36 Matrix ans = Matrix(); 37 for(int i = 1; i <= m.r; i++) { 38 ans.m[i][i] = 1LL; 39 } 40 ans.r = m.r; 41 ans.c = m.c; 42 while(n) { 43 if(n & 1) { 44 ans = mul(m, ans, mod); 45 } 46 m = mul(m, m, mod); 47 n >>= 1; 48 } 49 return ans; 50 } 51 52 int main() { 53 //freopen("in", "r", stdin); 54 int T; 55 scanf("%d", &T); 56 while(T--) { 57 scanf("%d",&n); 58 Matrix A; A.c = A.r = 2; 59 A.m[1][1] = 1; A.m[1][2] = 1; A.m[2][1] = 1; A.m[2][2] = 0; 60 Matrix B; B.c = B.r = 2; 61 B = quickmul(A,n,mod1); 62 n = B.m[1][2]; 63 A.m[1][1] = 1; A.m[1][2] = 1; A.m[2][1] = 1; A.m[2][2] = 0; 64 B = quickmul(A,n,mod); 65 printf("%lld\n",B.m[1][2]%mod); 66 } 67 return 0; 68 }
A.用个线段树维护下就可以,也可以离线+倍增。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define lrt rt << 1 5 #define rrt rt << 1 | 1 6 const int maxn = 100100; 7 const int maxm = maxn << 2; 8 char s[maxn]; 9 int q, n; 10 int asc[256]; 11 typedef struct Pair { 12 int x, y; 13 Pair(){} 14 Pair(int x,int y):x(x),y(y){} 15 }Pair; 16 typedef struct Node { 17 Pair s[4]; 18 Node() { for(int i = 0; i < 4; i++) s[i].x = i, s[i].y = 0; } 19 }Node; 20 21 Node sum[maxm]; 22 23 Node f(Node a, Node b) { 24 Node ret; 25 for(int i = 0; i < 4; i++) { 26 int x = b.s[a.s[i].x].x; 27 int y = (a.s[i].x - i + 4) % 4 + (x - a.s[i].x + 4) % 4; 28 ret.s[i] = Pair(x, a.s[i].y+b.s[a.s[i].x].y+(y>=4)); 29 } 30 return ret; 31 } 32 void build(int rt, int l, int r) { 33 sum[rt] = Node(); 34 if(l == r) { 35 sum[rt].s[asc[s[l]]] = Pair((asc[s[l]]+1)%4, 0); 36 return; 37 } 38 int m = (l + r) >> 1; 39 build(lrt, l, m); build(rrt, m+1, r); 40 sum[rt] = f(sum[lrt], sum[rrt]); 41 } 42 Node query(int rt, int l, int r, int L, int R) { 43 if(L <= l && r <= R) return sum[rt]; 44 int m = (l + r) >> 1; 45 if(R <= m) return query(lrt,l,m,L,R); 46 else if(m < L) return query(rrt,m+1,r,L,R); 47 else return f(query(lrt,l,m,L,m), query(rrt,m+1,r,m+1,R)); 48 } 49 50 int main() { 51 //freopen("in","r",stdin); 52 asc['e'] = 0; asc['a'] = 1; asc['s'] = 2; asc['y'] = 3; 53 int l, r; 54 while(~scanf("%s%d",s+1,&q)) { 55 n = strlen(s+1); 56 build(1,1,n); 57 while(q--) { 58 scanf("%d%d",&l,&r); 59 if(l > r) swap(l, r); 60 if(r-l+1<4) puts("0"); 61 else printf("%d\n", query(1,1,n,l,r).s[0].y); 62 } 63 } 64 return 0; 65 }