Time Limit: 1000Ms
Memory Limit: 65536KB
2 rrrjj rrrj rj jr
Yes No
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <set> #include <map> #include <queue> #include <stack> using namespace std; string remove_duplicates(string s) { return string(s.begin(), unique(s.begin(), s.end())); } int main(){ int T; cin >> T; string s,t; while (T--) { cin >> s; s = remove_duplicates(s); cin >> t; t = remove_duplicates(t); if (s.compare(t) == 0){ puts("Yes"); }else { puts("No"); } // cout << s << endl << t<< endl;; } }
Time Limit: 1000ms
Memory Limit: 65536KB
2 0.0000000000 0.0000000000 -3.0000000000 -3.0000000000 5.0000000000 5.0000000000 6.0000000000 6.0000000000 8.0000000000 8.0000000000 0.0000000000 0.0000000000 -2.0000000000 -2.0000000000 5.0000000000 5.0000000000 6.0000000000 6.0000000000 7.0000000000 7.0000000000
yes no
/*====================================================== # Author: whai # Last modified: 2016-01-09 17:29 # Filename: banana.cpp ======================================================*/ #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <set> #include <map> #include <queue> #include <stack> using namespace std; #define LL long long #define PB push_back #define X first #define Y second const double eps = 1e-8; struct Point { double x, y; Point() {} Point(double _x, double _y) { x = _x; y = _y; } void scan() { scanf("%lf%lf", &x, &y); } Point operator + (Point a) { return Point(x + a.x, y + a.y); } Point operator - (Point a) { return Point(x - a.x, y - a.y); } double operator * (Point a) { return x * a.x + y * a.y; } double operator ^ (Point a) { return x * a.y - y * a.x; } Point rotate() { return Point(-y, x); } double len() { return *this * *this; } }; Point P, Q; Point A[1], B[2]; int sgn(double x) { if (x == 0) return 0; if (x < 0) return -1; return 1; } double get_min_d(Point O, Point C, Point D) { double min_d = min((O - C).len(), (O - D).len()); Point OC = C - O; Point OD = D - O; Point OH = (D - C).rotate(); if(sgn(OH ^ OC) * sgn(OH ^ OD) != -1) //trick return min_d; double s = fabs(OC ^ OD); double h2 = s * s / (C - D).len(); return h2; } bool gao(Point O, Point C, Point D, double R) { double max_d = max((O - C).len(), (O - D).len()); double min_d = get_min_d(O, C, D); //cerr<<min_d<<' '<<R<<' '<<max_d<<endl; if(min_d - eps <= R && R <= max_d + eps) return true; return false; } int main() { int T; cin>>T; while(T--) { P.scan(); A[0].scan(); Q.scan(); B[0].scan(); B[1].scan(); Point PQ = Q - P; double R = PQ.len(); Point O = A[0] + PQ; bool ans = gao(O, B[0], B[1], R); if(ans) { puts("yes"); } else { //cerr<<P.x<<' '<<P.y<<' '<<A[0].x<<' '<<A[0].y<<endl; //cerr<<Q.x<<' '<<Q.y<<' '<<B[0].x<<' '<<B[0].y<<' '<<B[1].x<<' '<<B[1].y<<endl; puts("no"); } } return 0; }
Time Limit: 1000ms
Memory Limit: 65536KB
2 1 10 2 3 10 5
5 6
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <vector> using namespace std; typedef long long ll; int T,cas; ll a,b,n; vector<ll> adj; ll solve(ll x,ll n) { adj.clear(); ll i,j; for (i=2;i*i<=n;i++) if (n%i==0) { adj.push_back(i); while (n%i==0) n/=i; } if (n>1) adj.push_back(n); ll sum=0,value,cnt; for (i=1;i<(1<<adj.size());i++) { value=1; cnt=0; for (j=0;j<adj.size();j++) if (i&(1<<j)) { value*=adj[j]; cnt++; } if (cnt&1) sum+=x/value; else sum-=x/value; } return x-sum; } int main() { //cas=0; scanf("%d",&T); while (T--) { scanf("%lld%lld%lld",&a,&b,&n); printf("%lld\n",solve(b,n)-solve(a-1,n)); } return 0; }
Time Limit: 3000MS
Memory Limit: 65536KB
15 1
10
简单的莫比乌斯反演
令f(d)表示x,y,z的gcd=d的个数
则F(d)表示x,y,z的gcd是d的倍数的个数
/*====================================================== # Author: whai # Last modified: 2016-01-11 13:13 # Filename: triple.cpp ======================================================*/ #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <set> #include <map> #include <queue> #include <stack> using namespace std; #define LL long long #define PB push_back #define P pair<int, int> #define X first #define Y second const int N = 1e5 + 5; int mu[N]; void getMu() { for (int i = 1; i < N; ++i) { int target = i == 1 ? 1 : 0; int delta = target - mu[i]; mu[i] = delta; for (int j = 2 * i; j < N; j += i) mu[j] += delta; } } int cnt[N]; void deal(int x) { for(int i = 1; i * i <= x; ++i) { if(x % i == 0) { ++cnt[i]; int tmp = x / i; if(tmp != i) { ++cnt[tmp]; } } } } LL F(int x) { LL tmp = cnt[x]; if(tmp < 3) return 0; return tmp * (tmp - 1) * (tmp - 2) / 6; } void gao(int n, int m) { LL ans = 0; for(int i = 1; i * m < N; ++i) { ans += mu[i] * F(i * m); } cout<<ans<<endl; } void init() { memset(cnt, 0, sizeof(cnt)); } int main() { getMu(); int T; scanf("%d", &T); while(T--) { int n, m; scanf("%d%d", &n, &m); init(); for(int i = 1; i <= n; ++i) { deal(i); } gao(n, m); } return 0; }
Time Limit: 8000MS
Memory Limit: 65536KB
4 6 4 3 3 5 2 5 2 4
9
三个条件一个一个干
对于第一个和第二个条件,其实就是说有一些组必须在一起
那我们就让他们在一起(在一起!在一起!)。。。。
因为他要求每一对都要满足fi, ci所以搞一个最大值的后缀就好了。。。
具体见标程reset函数
然后就是第三个条件和最后要求的东西
显然直觉上二分,二分答案S
然后题目就变成了,所有分组的的最大值的和需要尽量小ANS。
并且在这个尽量小的情况下,判断一下ANS和limit的大小
logn
最后,那么得到 【所有分组的最大值的和的最小值】 呢?
显然DP,并且DP答案是单调上升的,然后单调队列优化。
由于过程中有删除插入操作所以上multiset。当然你可以手敲平衡树。
具体就是:
设DP[i]为,当到i为止的 【分组的最大值的和的最小值】。
那么有: dp[i] = min(dp[j] + max(C[j+1], ..., C[i])) (j<i) 然后因为有二分出的答案金钱的限制,所以j也有限制,先假设这里 j >= head
而 F[head-1] + F[head] + F[head+1] + ... + F[i] > S (我们二分的答案金钱上限)
对于head ~ i因为每一个DP要求的是区段的最大值,所以我们维护一个递减的队列q,
记录一个递减的ci
c[q[l]] > c[q[l+1]] > ....c[q[r]]
而任何在head ~ i之间的dp[j] + max(xx)这个max(xx)都在这个序列中。
显然这时候,因为dp[i]是一个递增的序列,所以对于每一个q[i],总是与尽量前面的dp[i]合体,能得带更小的值。
dp[i] = min(c[q[l]] + dp[head-1],
c[q[l+1]] + dp[que[l]], c[q[l+2]] + dp[que[l+1]], ..., c[que[r]]+dp[que[r-1]]) ;
而这个东西用set维护,与队列共存
nlogn
总复杂度 n(logn)(logn)
#include <iostream> #include <string> #include <string.h> #include <cstdio> #include <set> // #include <ctime> using namespace std; const int maxn = 1e5+5; const int inf = 1e9+7; int n, limit; int c[maxn], f[maxn]; void reset(){ static int c_max[maxn], cc[maxn], ff[maxn]; c_max[n+1] = -1; for(int i=n;i>=1;i--) c_max[i] = max(c[i], c_max[i+1]); int nn = 0, f_min = inf, st = 1; for(int i=1;i<=n;i++){ f_min = min(f_min, f[i]); if ( f_min > c_max[i+1] || i==n ){ nn++; cc[nn] = 0, ff[nn] = 0; for(int j=st;j<=i;j++){ cc[nn] = max(cc[nn], c[j]); ff[nn] += f[j]; } st = i+1; f_min = inf; } } n = nn; for(int i=1;i<=n;i++) c[i] = cc[i], f[i] = ff[i]; } bool test(int s){ static int dp[maxn]; static int que[maxn], l, r; static multiset<int> myset; for(int i=1;i<=n;i++) if ( f[i]>s ) return false; r = 0, l = 1; myset.clear(); int sumf = 0, head = 1; dp[0] = 0; for(int i=1;i<=n;i++){ sumf += f[i]; // -> while ( head<i && sumf>s ) { sumf -= f[head++]; } // <- while ( l<=r && c[que[r]]<=c[i] ){ if ( l<r ) myset.erase( dp[que[r-1]] + c[que[r]] ); r--; } if( l<=r ) myset.insert( dp[que[r]] + c[i] ); que[++r] = i; // -> while ( l<=r && que[l]<head ){ if ( l<r ) myset.erase( dp[que[l]] + c[que[l+1]] ); l++; } dp[i] = dp[head-1] + c[ que[l] ]; if ( !myset.empty() ) dp[i] = min(dp[i], *myset.begin() ); } return dp[n] <= limit ; } int main(){ // double st = clock(); while ( scanf("%d%d", &n, &limit)!=EOF ){ for(int i=1;i<=n;i++) scanf( "%d%d", &c[i], &f[i] ); if ( n==0 ){ puts("0"); continue; } reset(); int l = 1, r = 0, mid; for(int i=1;i<=n;i++) r += f[i]; while ( l<r-1 ){ mid = (l+r)>>1; if ( test(mid) ) r = mid; else l = mid; } if ( test(r) ) mid = r; else if ( test(l) ) mid = l; else mid = -1; printf("%d\n", mid); } // double en = clock(); // cerr<<(en - st) / CLOCKS_PER_SEC<<endl; return 0; }
Time Limit: 1000MS
Memory Limit: 65536KB
2 5 7 6 9 8 10 5 5 4 3 2 1
2 5
经典贪心问题,从前往后扫描原数组,每到一个数,找个当前最大值最大的不降数组加入其中,否则新建一个不降数组。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <map> #include <queue> #include <stack> #include <cmath> using namespace std; int height[10000]; int main() { int T;cin>>T; while(T--) { int n;cin>>n; int number; int index = 0; while(n--) { scanf("%d",&number); int tmp_index = -1; for (int i = 0; i < index; ++i) { if(number>=height[i] && (tmp_index == -1 || height[tmp_index] < height[i])) { tmp_index = i; } } if(tmp_index != -1) { height[tmp_index] = number; } else height[index++] = number; } cout<<index<<endl; } }
Time Limit: 1000ms
Memory Limit: 65536KB
1 2 2
210526315789473684
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int ans[1005]; bool vis[10][10]; int n,k; int main(){ int cases; scanf("%d",&cases); for (int cas=1;cas<=cases;cas++){ scanf("%d%d",&n,&k); memset(ans,0,sizeof(ans)); int top=0; int x=n*k %10; int y=n*k /10; y+=(ans[top]+x)/10; x=(ans[top]+x)%10; //cout<<n<<'+'<<k<<endl; memset(vis,false,sizeof(vis)); bool flag=true; while (y!=0 || x!=n || (top>0 && ans[top-1]==0)){ ans[top]=x; ans[top+1]=y; if (vis[ans[top]][y]){ flag=false; break; } vis[ans[top]][y]=true; x=ans[top]*k %10; y=ans[top]*k /10; top++; y+=(ans[top]+x)/10; x=(ans[top]+x)%10; } ans[top]=x; ans[top+1]=y; top++; if (!flag){ puts("-1"); continue; } for (int i=top-1;i>=0;i--) printf("%d",ans[i]); putchar('\n'); } return 0; }
Time Limit: 1000MS
Memory Limit: 65536KB
3 1 5 2 1 231 1 1
Yamato_Saikou! Yamato_Saikou! Meidikeji_Shijiediyi!
奇异局势,所有堆xor和==0.
假定S是非奇异局势,T是奇异局势。
一堆中石子数量>=2,表示充裕堆, =1表示孤单堆。
S0即非奇异局势下,充裕堆为0的状态
S1即非奇异局势下,充裕堆为1的状态
S2即非奇异局势下,充裕堆>=2的状态
T0即奇异局势下,充裕堆为0的状态
T2即奇异局势下,充裕堆>=2的状态
1.奇异局势的定义可知,S能转移到T,能转移到S, T只能转移到S
2.S0必败,T0必胜
3.S1必胜,因为S1只需要转移到S0即可。
4.S2必胜,T2必败。
1)T2只能转移到S1 和 S2
2)若T2转移到S1 则T2败,若T2转移到S2,S2只需要转回到T2即可。所以S2胜,T2败。
所以:
必胜态:T0,S1,S2
必败态:S0,T2
//必胜:T0,S1,S2 //必败:S0,T2 #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; int main(){ int cases; scanf("%d",&cases); for (int cas=1;cas<=cases;cas++){ int n; scanf("%d",&n); int sum=0,ones=0; for (int i=1;i<=n;i++){ int x; scanf("%d",&x); sum^=x; if (x==1) ones++; } if (sum==0){ if (n-ones==0) puts("Yamato_Saikou!"); else puts("Meidikeji_Shijiediyi!"); } else { if (n-ones==0){ if (ones&1) puts("Meidikeji_Shijiediyi!"); //必定是奇数堆,非奇异局势 } else puts("Yamato_Saikou!"); } } return 0; }
Time Limit: 1000MS
Memory Limit: 65536KB
2 3 0 0 1 1 2 2 3 0 0 1 1 5 5
3 2
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <map> #include <stack> #include <assert.h> using namespace std; const int MAXN = 10000; int n, m; struct note { int u, v, c; note() {} note(int u, int v, int c): u(u), v(v), c(c) {} } p[MAXN]; int head[MAXN]; int next_[MAXN]; int dfn[MAXN]; int low[MAXN]; int instack[MAXN]; int belong[MAXN]; stack<int> sta; int e = 0; int indexx; int cnt = 0; int x[MAXN]; int y[MAXN]; void addnote(int u, int v, int c) { p[e] = note(u, v, c); next_[e] = head[u]; head[u] = e++; } void init() { for (int i = 0; i < MAXN; ++i) { head[i] = next_[i] = -1; } while(!sta.empty()) sta.pop(); memset(p, 0, sizeof(p)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(belong, 0, sizeof(belong)); memset(instack, 0, sizeof(instack)); e = 0; cnt = 0; indexx = 0; } void tarjan(int u) { //assert(u!=2*m); dfn[u] = low[u] = ++indexx; instack[u] = 1; sta.push(u); for (int i = head[u]; i != -1; i = next_[i]) { int v = p[i].v; if (!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if (instack[v]) low[u] = min(low[u], dfn[v]); } if (dfn[u] == low[u]) { int v; cnt++; do { v = sta.top(); sta.pop(); instack[v] = 0; belong[v] = cnt; } while (u != v); } } void solve() { for (int i = 0; i < 2 * m; i++) if (!dfn[i]) tarjan(i); } int main() { int T; cin >> T; while (T--) { cin >> m; for (int i = 0; i < m; ++i) { scanf("%d %d", &x[i], &y[i]); } int lower = 0, upper = m; while (lower <= upper) { init(); //cout<<"----------"<<endl; int mid = (lower + upper) >> 1; for (int i = 0; i < mid; ++i) { //printf("addnote(%d,%d)\n", 2 * n - 1 - x[i],y[i]); //printf("addnote(%d,%d)\n", 2 * n - 1 - y[i],x[i]); addnote(2 * m - 1 - x[i], y[i],1); addnote(2 * m - 1 - y[i], x[i],1); } solve(); bool flag = true; for (int i = 0; i < m && flag; ++i) { //printf("belong[%d]=%d;belong[%d]=%d;\n",i,belong[i],2 * m - 1 - i,belong[2 * m - 1 - i]); if (belong[i] == belong[2 * m - 1 - i]) { flag = false; } } if (flag) lower = mid + 1; else upper = mid - 1; //cout<<"----------"<<endl; } cout<<(lower+upper)/2<<endl; } return 0; }
Time Limit: 1000MS
Memory Limit: 65536KB
3 2 1 6 5 4 3
19
找一个最高点h、、
答案就是
(h+1)*sum(wi) - 各海拔
#include <iostream> #include <string> #include <string.h> #include <cstdio> #define LL long long using namespace std; const int maxn = 1e5+5; int n; int h[maxn],w[maxn]; int main(){ while ( scanf("%d",&n)!=EOF ){ if ( n==0 ){ puts("1"); continue; } int maxh = -1; for(int i=1;i<=n;i++){ scanf("%d%d", &h[i], &w[i]); maxh = max(maxh, h[i]); } LL ans = 0; for(int i=1;i<=n;i++) ans += (LL)w[i] * (maxh+1 - h[i]); printf("%lld\n", ans); } return 0; }