答案是node
\(\prod_{c = 'a'}^{'z'} (cnt[c] + 1)\)c++
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 200005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int N; char s[MAXN]; int cnt[35]; void Solve() { read(N); scanf("%s",s + 1); for(int i = 1 ; i <= N ; ++i) { cnt[s[i] - 'a']++; } int res = 1; for(int i = 0 ; i < 26 ; ++i) { res = 1LL * res * (1 + cnt[i]) % MOD; } res = (res + MOD - 1) % MOD; out(res);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
記\(dp[i][0/1]\)表示沒有進行操做/進行了操做ui
\(dp[i][0] = dp[i - 1][0] + dp[i - 1][1]\)spa
若是\(C[i - 1] == C[i]\),那麼不能進行操做code
不然能夠從前面全部\(C[k - 1] != C[k]\)且\(C[i] == C[k]\)的地方轉移過來;遞歸
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 200005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int N,C[MAXN],sum[MAXN]; int dp[MAXN][2]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { read(C[i]); } dp[0][0] = 1; for(int i = 1 ; i <= N ; ++i) { dp[i][0] = inc(dp[i - 1][1],dp[i - 1][0]); if(C[i] != C[i - 1]) { dp[i][1] = sum[C[i]]; sum[C[i]] = inc(sum[C[i]],dp[i][0]); } } out(inc(dp[N][0],dp[N][1]));enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
這道題用數學概括法ip
A和B中1的奇偶性必須不一樣get
顯然N = 1的的時候確定成立數學
若是\(N = K +1\),且\(N = K\)時成立it
這個時候找\(A\)和\(B\)中不一樣的一位,刪掉,此時\(A\)和\(B\)中1的奇偶性相同
而後如今是兩個\(K\)位數,咱們設一個\(K\)位數\(C\),和\(A,B\)的1的奇偶性不一樣
而後\(A\)到\(C\)能夠到達,\(C\)到\(B\)也能夠達到,遞歸處理,而後將前\(2^K\)刪掉的位置添加上,且與\(A\)相同,後\(2^{K}\)刪掉的位置添加上和\(B\)相同
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 200005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,A,B; int Delete(int x,int p) { int d = x & (1 << p) - 1; int u = x & (1 << 20) - (1 << p + 1); return (u >> 1) + d; } int Insert(int x,int p,int v) { int d = x & (1 << p) - 1; int u = x & (1 << 20) - (1 << p); return (u << 1) + v + d; } vector<int> Calc(int s,int t,int n) { if(n == 1) { vector<int> v;v.pb(s);v.pb(t); return v; } int x = 1,p = 0; while(1) { if((s & x) != (t & x)) break; x <<= 1;++p; } int a,b; a = Delete(s,p);b = Delete(t,p); int c = a ^ 1; vector<int> f = Calc(a,c,n - 1),h = Calc(c,b,n - 1); for(int i = 0 ; i < (1 << n - 1) ; ++i) { f[i] = Insert(f[i],p,(s & x)); h[i] = Insert(h[i],p,(t & x)); } f.insert(f.end(),h.begin(),h.end()); return f; } int count(int x) { int res = 0; while(x) { res += (x & 1); x >>= 1; } return res; } void Solve() { read(N);read(A);read(B); if(!(count(A^B) & 1)) {puts("NO");return;} puts("YES"); vector<int> ans = Calc(A,B,N); for(int i = 0 ; i < (1 << N) ; ++i) { out(ans[i]);space; } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
設\(p\cdot q = t\),\(t_{i} = p_{q_{i}}\)
這裏面\(a_{2} = q\cdot p^{-1}\)
咱們把這個寫成\(a = ABA^{-1}\)的形式
能夠獲得
設\(a = (A,B)\)
\(a_{1} = (id,p)\)
\(a_{2} = (id,q)\)
\(a_{3} = (id,qp^{-1})\)
\(a_{4} = (q,p^{-1})\)
\(a_5 = (qp^{-1},q^{-1})\)
\(a_6 = (qp^{-1},q^{-1}p)\)
\(a_{7} = (qp^{-1}q^{-1}p,p)\)
\(a_8 = (qp^{-1}q^{-1}p,q)\)
發現6次B一個重複
前面是\(qp^{-1}q^{-1}p\)的\(\lfloor \frac{K - 1}{6}\rfloor\)次冪
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 100005 #define eps 1e-10 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,K; struct pl { int f[100005]; friend pl operator * (const pl &a,const pl &b) { pl c; for(int i = 1 ; i <= N ; ++i) c.f[i] = a.f[b.f[i]]; return c; } pl inv() { pl c; for(int i = 1 ; i <= N ; ++i) { c.f[f[i]] = i; } return c; } }p,q,iq,ip,s,res,t,ans; void fpow(int c) { for(int i = 1 ; i <= N ; ++i) res.f[i] = i; t = s; while(c) { if(c & 1) res = res * t; t = t * t; c >>= 1; } } void Solve() { read(N);read(K); for(int i = 1 ; i <= N ; ++i) read(p.f[i]); for(int i = 1 ; i <= N ; ++i) read(q.f[i]); ip = p.inv();iq = q.inv(); s = q * ip * iq * p; fpow((K - 1) / 6); int x = (K - 1) % 6; if(x == 0) { ans = res * p * res.inv(); } else if(x == 1) { ans = res * q * res.inv(); } else if(x == 2) { ans = res * q * ip * res.inv(); } else if(x == 3) { res = res * q; ans = res * ip * res.inv(); } else if(x == 4) { res = res * q * ip; ans = res * iq * res.inv(); } else if(x == 5) { res = res * q * ip; ans = res * iq * p * res.inv(); } for(int i = 1 ; i <= N ; ++i) { out(ans.f[i]);space; } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
假如只能選K個,那麼咱們能夠建出限制
對於一維的,若是是小於等於\(a\)最多選\(b\)個,那麼至關於第\(b+1\)個必須在大於等於\(a + 1\)
若是大於等於\(a\)最多選\(b\)個,那麼至關於第\(K - b\)個必須在小於等於\(a - 1\)處
這樣能夠對於每個求一個左右限制出來
知足
\(L_{1} \leq L_{2} \leq L_{3}\leq \cdots \leq L_{k}\)
\(R_{1} \leq R_{2} \leq R_{3} \leq \cdots \leq R_{k}\)
而後對兩維都求這個限制
建K個點表示x軸上選的第幾個,K個點表示y軸上選的第幾個
而後2N個點表示每一個珠寶各兩個點,中間連一條容量爲1,價值爲珠寶價值的邊
而後前K個表示x軸上的點,和x符合條件的珠寶連一條容量爲1代價爲0的邊
而後每一個珠寶的第二個點和自身y匹配哪一個限制連一條容量爲1代價爲0的邊
而後原點向前K個連一條邊,後K個向匯點連一條邊,都是容量爲1價值爲0
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 100005 #define eps 1e-10 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } struct node { int to,next,cap;int64 val; }E[1000005]; int sumE,head[505],a[330],b[330],x[85],y[85],N,M; int L[2][85],R[2][85],S,T,f; int64 val[85],res,ans,ex; bool vis[505]; char s[330][2]; void add(int u,int v,int c,int64 a) { E[++sumE].to = v; E[sumE].next = head[u]; E[sumE].cap = c; E[sumE].val = a; head[u] = sumE; } void addtwo(int u,int v,int c,int64 a) { add(u,v,c,a); add(v,u,0,-a); } void build(int K) { sumE = 1;memset(head,0,sizeof(head)); for(int i = 1 ; i <= N ; ++i) L[0][i] = L[1][i] = 1,R[0][i] = R[1][i] = 100; for(int i = 1 ; i <= M ; ++i) { if(b[i] >= K) continue; if(s[i][0] == 'L') { L[0][b[i] + 1] = max(L[0][b[i] + 1],a[i] + 1); } else if(s[i][0] == 'R') { R[0][K - b[i]] = min(R[0][K - b[i]],a[i] - 1); } else if(s[i][0] == 'D') { L[1][b[i] + 1] = max(L[1][b[i] + 1],a[i] + 1); } else if(s[i][0] == 'U') { R[1][K - b[i]] = min(R[1][K - b[i]],a[i] - 1); } } for(int i = 2 ; i <= K ; ++i) { L[0][i] = max(L[0][i - 1],L[0][i]); L[1][i] = max(L[1][i - 1],L[1][i]); } for(int i = K - 1 ; i >= 1 ; --i) { R[0][i] = min(R[0][i + 1],R[0][i]); R[1][i] = min(R[1][i + 1],R[1][i]); } S = 1;T = 2 * K + 2 * N + 2; for(int i = 1 ; i <= K ; ++i) { addtwo(S,i + 1,1,0); addtwo(i + K + 2 * N + 1,T,1,0); for(int j = 1 ; j <= N ; ++j) { if(x[j] >= L[0][i] && x[j] <= R[0][i]) { addtwo(i + 1,K + j + 1,1,0); } if(y[j] >= L[1][i] && y[j] <= R[1][i]) { addtwo(K + N + j + 1,i + K + 2 * N + 1,1,0); } } } for(int i = 1 ; i <= N ; ++i) { addtwo(K + i + 1,K + N + i + 1,1,val[i]); } } int maxflow(int u,int aug) { if(u == T) { res += ex * aug; f += aug; return aug; } int flow = 0; vis[u] = 1; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(E[i].cap > 0 && !vis[v] && E[i].val == 0) { int t = maxflow(v,min(E[i].cap,aug - flow)); flow += t; E[i].cap -= t; E[i ^ 1].cap += t; } } return flow; } bool modlabel() { int64 p = -1e18; for(int u = S ; u <= T ; ++u) { if(vis[u]) { for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(!vis[v] && E[i].cap > 0 && E[i].val > p) p = E[i].val; } } } if(p == -1e18) return false; ex += p; for(int u = S ; u <= T ; ++u) { if(vis[u]) { for(int i = head[u] ; i ; i = E[i].next) { E[i].val -= p; E[i ^ 1].val += p; } } } return true; } void Init() { read(N); for(int i = 1 ; i <= N ; ++i) { read(x[i]);read(y[i]);read(val[i]); } read(M); for(int i = 1 ; i <= M ; ++i) { scanf("%s",s[i]);read(a[i]);read(b[i]); } } void Solve() { ans = 0; for(int i = 1 ; i <= N ; ++i) { build(i); res = 0;ex = 0; f = 0; do { do { memset(vis,0,sizeof(vis)); }while(maxflow(1,i)); }while(modlabel()); if(f == i) ans = max(ans,res); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); }
這道題特別神仙
反着來考慮,咱們設\((v,x)\)表示\(v\)這個點有價值爲\(x\),那麼若是有一條邊\((u,v,c)\),那麼咱們能夠走到的狀態是\((u,2x +c) \rightarrow (v,4x + 3c) \rightarrow (u,8x + 7c)\cdots\)
由於模數是奇數嘛,這麼乘下去,必定會獲得\(1\)的,感性理解可參照費馬小定理
那麼咱們就知道了
\((v,x)\rightarrow(u,2x + c)\)
\((u,2x+c)\rightarrow(v,x)\)
這是一個雙射
而後就是,若是一個點有代價爲\(a\)和代價爲\(b\)的邊直接相連,那麼它能夠走到
\((v,x)\Leftrightarrow (v,4x + 3a)\)
\((v,x)\Leftrightarrow (v,4x + 3a)\)
咱們能夠選擇這條路
\((v,4x + 3a) \rightarrow (v,x) \rightarrow(v,4x + 3b)\)
事實上,咱們存在對4的逆元,那麼\(4x\)能夠表示任何數,那麼咱們就又獲得了一條性質
\((v,x) \rightarrow (v,x + 3k(a - b)),k \in \Z\)
若是咱們對於全部的邊權之差和MOD求一個gcd,設爲\(g\),\(g|a - b\)且\(g|b - c\)那麼\(g|a - c\)因此這個\(g\)能夠經過每條邊減第一條邊的絕對值的和MOD求gcd得到
事實上,咱們的運算能夠在\(gcd(MOD,3g)\)意義下進行
爲何呢,顯然咱們的模數要麼是\(g\)要麼是\(3g\)
若是是\(g\)的話,\(MOD\)和\(3\)互質,且必定存在兩個不一樣的邊權之差\(a - b\)和\(d - c\)互質,圖是聯通的,咱們能夠經過這兩個互質的邊權之差構造出,根據同餘方程,而後這個時候和3又互質,因此3存在逆元,咱們又能夠構造出任意數,因此模\(g\)意義下相等的就都相等了
\(3g\)也是同理的。。。
好的,這個問題解決了,那麼咱們修改了模數後,全部的邊權都相等了
那麼如今有個問題,若是\((v,x)\rightarrow (u,2x + c)\)
如今咱們是\((v,x)\rightarrow (u,2x + z + pg),(0 \leq p < 3)\)
看起來問題沒什麼實質性解決
可是若是咱們認爲\(x' = x + z\)邊權減去\(z\)
從\(x \rightarrow 2x + z + pg\)
就是\(x' \rightarrow 2x' + pg = 2x + 2z + pg - z\)
這樣的話邊權都是g的倍數了,也知足\((v,x) \rightarrow (v,2x + c)\)
這樣看起來很棒,那麼就這樣吧
因而咱們的詢問能夠從\((t,z)\)到\((s,r + z)\)
那麼一個點能夠被表示成
由於\((v,x) \rightarrow (v,4x + 3c)\),並且\(c\)又是\(g\)的倍數,那麼認爲\((v,x) \rightarrow(v,4x)\)
那麼就有\((v,2^{q}x + pg)\),\((0\leq q \leq 1,0 \leq p \leq 2)\)
這樣圖裏只有6個點了,咱們能夠用並查集連一下
查詢的時候
查\((t,x)\)和\((s,2^{p}x + qg)\)是否連通
這個能夠獲得
\(2^{p}z + qg = r + z\)
那麼看一下\(r + z - qg\)是2的奇數次冪乘\(x\)仍是2的偶數次冪乘\(x\)
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int maxn = 5e5 + 5,maxm = 1e6 + 5;; int N,M,Q,MOD,f[maxn],t[maxn],v[maxn]; int fa[maxm * 6],z,g; bool able[2][maxm]; int id(int u,int p,int q) { return (u - 1) * 6 + p * 3 + q + 1; } int gcd(int a,int b) { return b == 0 ? a : gcd(b,a % b); } int getfa(int u) { return u == fa[u] ? u : fa[u] = getfa(fa[u]); } void Merge(int u,int v) { fa[getfa(u)] = getfa(v); } void Init() { read(N);read(M);read(Q);read(MOD); read(f[1]);read(t[1]);read(v[1]); g = MOD; for(int i = 2 ; i <= M ; ++i) { read(f[i]);read(t[i]);read(v[i]); g = gcd(g,abs(v[i] - v[1])); } MOD = gcd(MOD,3 * g); z = v[1] % g; int T = id(N,1,2); for(int i = 1 ; i <= T; ++i) fa[i] = i; for(int i = 1 ; i <= M ; ++i) { int w = (v[i] / g) % 3; for(int p = 0 ; p < 2 ; ++p) { for(int q = 0 ; q < 3 ; ++q) { Merge(id(f[i],p,q),id(t[i],p ^ 1,(q * 2 + w) % 3)); Merge(id(t[i],p,q),id(f[i],p ^ 1,(q * 2 + w) % 3)); } } } for(int i = 0 , j = z ; i < MOD ; ++i , j = j * 2 % MOD) able[i & 1][j] = 1; } void Solve() { int s,t,r; for(int i = 1 ; i <= Q ; ++i) { read(s);read(t);read(r); bool res = 0; for(int p = 0 ; p < 2 ; ++p) { for(int q = 0 ; q < 3 ; ++q) { if(getfa(id(t,0,0)) == getfa(id(s,p,q))) { if(able[p][(r + z + (3 - q) * g) % MOD]) res = 1; } } } if(res) puts("YES"); else puts("NO"); } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); }