AGC编号越小越水????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 eps 1e-10 #define MAXN 500005 //#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); } string s; map<char,int> zz; void Solve() { cin >> s; for(int i = 0 ; i < s.length() ; ++i) zz[s[i]] = 1; if((zz['W'] ^ zz['E']) & 1) {puts("No");return;} if((zz['N'] ^ zz['S']) & 1) {puts("No");return;} puts("Yes"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
先把每一个卡本身都配对,取模2spa
而后剩余的单张卡若是距离下一张单张卡之间的卡都有对子,那么拆掉这些对子能够得到加1的贡献,扫一遍就行了code
#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 MAXN 100005 //#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[MAXN],pa[MAXN]; int64 ans = 0; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { read(A[i]); ans += A[i] / 2; pa[i] = A[i] / 2; A[i] %= 2; } int pre = -1; for(int i = 1 ; i <= N ; ++i) { if(A[i]) { if(pre == -1) pre = i; else {pre = -1;++ans;} } else { if(!pa[i]) pre = -1; } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
由于三个交换不改变每一个数所在位置的奇偶性,若是一个数的目标位置和本身所在位置的奇偶性不一样那么就须要一次Op1ci
计算全部当前位置和目标位置奇偶性不一样的位置除二便可get
#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 MAXN 100005 //#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 cnt[2],A[MAXN],N,B[MAXN]; map<int,int> zz; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) {read(A[i]);B[i] = A[i];} sort(B + 1,B + N + 1); for(int i = 1 ; i <= N ; ++i) zz[B[i]] = i; for(int i = 1 ; i <= N ; ++i) { if(((zz[A[i]] ^ i) & 1) != 0) cnt[i & 1]++; } out(cnt[0]);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
先用\(\sqrt[3]{10^{10}}\)给全部的数的质数指数幂取模3string
初始答案设成N,统计1的个数是cnt,若cnt不为0,答案减掉cnt - 1it
而后分析一下,每一个数只有惟一的一个各个质数指数不超过3的数和这个数配对使得这个数成为立方数io
如何找这个数呢,质因数分解显然会超时class
可是分析一下,若是只有一个质数的话,咱们特判掉,而后咱们默认用配对的数中的小的和大的配,这样的话质数最大的范围能够这么考虑
若是这个数是\(pq\)的话,\(p,q\)都是质数,和它配对的是\(p^{2}q^{2}\),这个数也要在\(10^{10}\)的范围内,因此至多只有一个数大于\(\sqrt[4]{10^{10}}\)
若是这个数是\(p^2q\),配对的是\(pq^{2}\),那么至多只有一个数大于\(\sqrt[3]{10^{10}}\)
且最大的那个质数不大于\(10^{5}\)
因此咱们预处理出\(10^5\)之内每一个数是否是质数用来判断,质数分解的时候只须要用\(\sqrt[3]{10^{10}}\)之内的
这样大概不到1s就过了
#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 MAXN 100005 //#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; int64 S[MAXN],pre[1000005]; int prime[MAXN],tot,cnt; bool nonprime[MAXN]; map<int64,int> zz; int s[7] = {4,7,11,29,47,71,87}; vector<int64> v; int64 mul(int64 a,int64 b,int64 MOD) { int64 res = 0,t = a; while(b) { if(b & 1) res = (res + t) % MOD; t = (t + t) % MOD; b >>= 1; } return res; } int64 fpow(int64 a,int64 c,int64 MOD) { int64 res = 1,t = a; while(c) { if(c & 1) res = mul(res,t,MOD); t = mul(t,t,MOD); c >>= 1; } return res; } bool check(int64 s,int t,int64 MOD) { if(s == 1) return true; for(int i = 1 ; i <= t ; ++i) { int64 nxt = mul(s,s,MOD); if(nxt == 1) { if(s == MOD - 1) return true; return false; } } return false; } bool miller_rabin(int64 x) { int t = 0;int64 tmp = x - 1; while(tmp % 2 == 0) {++t;tmp /= 2;} for(int i = 0 ; i < 7 ; ++i) { if(!check(fpow(s[i],tmp,x),t,x)) return false; } return true; } void Solve() { read(N); for(int64 i = 1 ; i <= 1000000 ; ++i) pre[i] = i * i * i; for(int64 i = 2 ; i <= 100000 ; ++i) { if(!nonprime[i]) { prime[++tot] = i; } for(int j = 1 ; j <= tot ; ++j) { if(i * prime[j] > 100000) break; nonprime[i * prime[j]] = 1; if(i % prime[j] == 0) break; } } int ans = N; for(int i = 1 ; i <= N ; ++i) { read(S[i]); for(int j = 1 ; j <= 500 ; ++j) { if(pre[prime[j]] > S[i]) break; while(S[i] % pre[prime[j]] == 0) S[i] /= pre[prime[j]]; } if(S[i] == 1) ++cnt; else {zz[S[i]]++;v.pb(S[i]);} } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); if(cnt > 1) ans -= (cnt - 1); for(auto num : v) { int64 t = sqrt(num); if(t * t == num) continue; if(num <= 100000 && !nonprime[num]) {ans -= min(zz[num],zz[num * num]);} else { int64 x = num; int64 op = 1; for(int i = 1 ; i <= 500 ; ++i) { if(prime[i] > 3500 || prime[i] > x) break; if(x % prime[i] == 0) { int c = 0; while(x % prime[i] == 0) {x /= prime[i];++c;} c = 3 - c; op = op * prime[i]; if(op > 1e10) goto fail; if(c == 2) op = op * prime[i]; if(op > 1e10) goto fail; } } if(x != 1) { if(x <= 100000) { if(nonprime[x]) goto fail; for(int i = 0 ; i < 2 ; ++i) { op = op * x; if(op > 1e10) goto fail; } } else { goto fail; } } if(op > num) ans -= min(zz[num],zz[op]); } fail:; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
用一个单调栈,每次来一个操做弹出到第一个小于它的,而后咱们获得一个新的操做序列这个和原来的操做序列结果是同样的
这个时候咱们每次操做都是递增的,第一个大小是a的话,那么第一个序列就是1,2,3,4...a
而后咱们把栈顶的统计次数设为1,sta[i - 1]的统计次数要加上是\(sta[i] / sta[i - 1] * cnt[i]\)
而后咱们有一个余数是\(sta[i] \% sta[i - 1]\)
咱们二分找到第一个小于这个余数的序列,计算余数除这个序列的次数乘上本序列统计次数加到这个序列上,而后余数取模序列长度,直到余数小于等于一个序列大小,此时若为b,ans[b] += cnt[i],以后统计一个后缀和就是答案
由于每次取模余数都会减小一半,因此复杂度是$Q \log{max{ q{i}}} \log N $
#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 MAXN 100005 //#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,Q,top; int64 sta[MAXN]; int64 cnt[MAXN],ans[MAXN]; void Solve() { read(N);read(Q); sta[++top] = N; int64 p; for(int i = 1 ; i <= Q ; ++i) { read(p); while(top && sta[top] >= p) --top; sta[++top] = p; } cnt[top] = 1; for(int i = top ; i >= 1 ; --i) { if(i != top) cnt[i] += cnt[i + 1] * (sta[i + 1] / sta[i]); if(i == 1) {ans[sta[1]] += cnt[1];continue;} int64 r = sta[i] % sta[i - 1]; while(r > sta[1]) { int t = upper_bound(sta + 1,sta + top + 1,r) - sta - 1; cnt[t] += cnt[i] * (r / sta[t]); r %= sta[t]; } ans[r] += cnt[i]; } for(int i = N ; i >= 1 ; --i) ans[i] += ans[i + 1]; for(int i = 1 ; i <= N ; ++i) { out(ans[i]);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve();mahjong return 0; }
简单分析一下,若是初始图形复制一份左右拼接不上,上下拼接不上,那就是黑色个数的\(K - 1\)次方
若是左右拼上,上下拼上,那就是1
若是只有左右拼上,初始认为每个黑格子都会新造成一个联通块,那么新来一个右边会减小1,此时若是左右拼上的行不少,那么过了一个level以后,这些行也会相链接致使联通块减小
因此对于每一个方块统计它右边有没有方块,记为h,以及能起始和终止都有黑格子的行有几个,记为a,总联通块个数记为b
那么\(f(k + 1) = bf(k) - h * a^{k - 1}\)
这个用矩阵乘法优化一下就行了
若是只有上下拼上是同理的
#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 MAXN 100005 //#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 H,W,all,h,c; int64 K; char s[1005][1005]; 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 update(int &x,int y) { x = inc(x,y); } struct Matrix { int f[2][2]; Matrix() {memset(f,0,sizeof(f));} friend Matrix operator * (const Matrix &a,const Matrix &b) { Matrix c; for(int i = 0 ; i < 2 ; ++i) { for(int j = 0 ; j < 2 ; ++j) { for(int k = 0 ; k < 2 ; ++k) { update(c.f[i][j],mul(a.f[i][k],b.f[k][j])); } } } return c; } }a,ans; Matrix fpow(Matrix x,int64 c) { Matrix res,t = x; res.f[0][0] = res.f[1][1] = 1; while(c) { if(c & 1) res = res * t; t = t * t; c >>= 1; } return res; } int fpow(int x,int64 c) { int64 res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } void Solve() { read(H);read(W);read(K); if(K == 0 || K == 1) {puts("1");return;} for(int i = 1 ; i <= H ; ++i) scanf("%s",s[i] + 1); for(int i = 1 ; i <= H ; ++i) { for(int j = 1 ; j <= W ; ++j) { if(s[i][j] == '#') { ++all; if(s[i][j + 1] == '#') ++h; if(s[i + 1][j] == '#') ++c; } } } bool f1 = 0;int c1 = 0; for(int i = 1 ; i <= H ; ++i) { if(s[i][1] == '#' && s[i][W] == '#') {f1 = 1;++c1;} } bool f2 = 0;int c2 = 0; for(int i = 1 ; i <= W ; ++i) { if(s[1][i] == '#' && s[H][i] == '#') {f2 = 1;++c2;} } if(f1 && f2) {puts("1");return;} if(!f1 && !f2) { out(fpow(all,K - 1));enter;return; } if(f1) { a.f[1][0] = MOD - h; a.f[1][1] = c1; } else if(f2) { a.f[1][0] = MOD - c; a.f[1][1] = c2; } a.f[0][0] = all; ans = fpow(a,K - 1); out(inc(ans.f[0][0],ans.f[1][0]));enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }