D1T1
对于一个格点图,类似于男人八题T1,我们这道题也可以先找出矩形,之后再找出不是矩形的 平行四边形。 0 0 0 0 0 0 0 0 0 0 我们采取上次同样的策略来找,发现规律: S = (3 + 2 + 1) (2 + 1) 1 (1 + 2) (1 + 2 + 3) 怎么总结呢? 我们发现:其实就是1 * n + ... + n * n - 2 - 6 - 12- ...我们再次发现(我们好厉害) 后面减去的那一坨其实就是2 * (S的一半) ok 再加上之前的矩形 规律为:(2n + 1)n(n + 1)/6
D1T2
对于这道题的话其实出题人已经很良心了,在输入的时候提示了,很容易想到折半搜索, 因为我们发现对于每个颜色的数量一定为n所以当我们在前半个n找出了p个的某个颜色,那么 这个某个颜色在另外的区间一定有n - p个,那么我们怎么统计合法方案呢?hash!!! 我们现在已经开始统计后半个区间,如果合法那么当前颜色的总hash值一定会有前半个的另外一个颜色的总hash值和它相等 //挂题原因 不会用map,实际上它很简单呢!! //可爱的小分割线 code: #include<cstdio> #include<iostream> #include<map> #define ll long long using namespace std; const long long mod = 1e18 + 17; map<ll,int>res[100]; long long ans,d[100]; int n,p,q; char c[100]; void dfs1(int u,ll col) { if(u == n + 1) { //cout << col << endl; res[p][col]++; return; } ll x; p++; x = (col + d[p] * (c[u] - 'a' + 1)) % mod; dfs1(u + 1,x); p--; q++; x = (col - d[q] * (c[u] - 'a' + 1)) % mod; dfs1(u + 1,x); q--; } void dfs2(int u,ll col) { if(u == n) { //cout << col << endl; ans += res[q][col]; return; } ll x; p++; x = (col - d[p] * (c[u] - 'a' + 1)) % mod; dfs2(u - 1,x); p--; q++; x = (col + d[q] * (c[u] - 'a' + 1)) % mod; dfs2(u - 1,x); q--; } int main() { cin >> n; scanf("%s",c + 1); d[1] = 31; for(int i = 2;i <= n;i += 1) d[i] = d[i - 1] * 31 % mod; dfs1(1,0); //cout << endl; dfs2(2 * n,0); cout << ans << endl; return 0; }
D1T3
聪聪叹气,审题是个好东西,对于这个题我们发现统计内含整点个数,其实就是找到这个三角形 为什么呢?因为我们有公式S = a + b/2 - 1,那么出题人还要求锐角三角形,可我们还有 a ^ 2 + b ^ 2 > c ^ 2(我们有的挺多)这样的话我们就把问题转化成立找三角形问题, 怎么找呢,三元环计数!三元环做法详解直接上链接 https://www.cnblogs.com/Dance-Of-Faith/p/9759794.html 注意重边的代价要翻倍毕竟一个三元环的度位2,1,0 b咋算??getgcd! OK完美 //挂题原因 审题失误以为相交边不会产生影响,并且我还不会三元环(我好菜娅),甚至还不会map 虽然我现在还是没A,不过还是感觉进步了,dalao看看否哪里WA了>嘤嘤嘤 //我是分割线 #include<cstdio> #include<iostream> #include<map> #include<algorithm> #include<cmath> using namespace std; const int MAXN = 3e5 + 17; const int mod = 998244353; struct node { int v,next; }e[MAXN]; map<int,map<int,int> >q; map<int,map<int,int> >w; map<int,map<int,double> >d; map<int,map<int,int> > h; int tot,top,head[MAXN],vis[MAXN],a1[MAXN],a2[MAXN],b1[MAXN],b2[MAXN],in[MAXN]; int getgcd(int a,int b) { if(a < b)swap(a,b); if(b == 0)return a; return getgcd(b,a % b); } long long gets(double x,double y,double z) { double p = (x + y + z) / 2; return sqrt(p * (p - x) * (p - y) * (p - z)); } void add(int u,int v) { e[++tot].v = v; e[tot].next = head[u]; head[u] = tot; } bool rui(int x,int y,int z) { if(x * x + y * y <= z * z)return 0; if(x * x + z * z <= y * y)return 0; if(y * y + z * z <= x * x)return 0; return 1; } double getd(double x,double y) { return sqrt(x * x + y * y); } int main() { int n; cin >> n; for(int i = 1;i <= n;i += 1) { cin >> a1[i] >> b1[i] >> a2[i] >> b2[i]; if(!q[a1[i]][b1[i]])q[a1[i]][b1[i]] = ++top; if(!q[a2[i]][b2[i]])q[a2[i]][b2[i]] = ++top; w[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]] = w[q[a2[i]][b2[i]]][q[a1[i]][b1[i]]] = getgcd(abs(a2[i] - a1[i]),abs(b2[i] - b1[i])); d[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]] = d[q[a2[i]][b2[i]]][q[a1[i]][b1[i]]] = getd(abs(a2[i] - a1[i]),abs(b2[i] - b1[i])); in[q[a1[i]][b1[i]]]++; in[q[a2[i]][b2[i]]]++; } for(int i = 1;i <= n;i += 1) { if(h[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]]) { h[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]]++; h[q[a2[i]][b2[i]]][q[a1[i]][b1[i]]] = h[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]] ; //w[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]] = w[q[a2[i]][b2[i]]][q[a1[i]][b1[i]]] = w[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]] + h[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]]; continue; } if(in[q[a1[i]][b1[i]]] < in[q[a2[i]][b2[i]]]) add(q[a2[i]][b2[i]],q[a1[i]][b1[i]]); if(in[q[a1[i]][b1[i]]] > in[q[a2[i]][b2[i]]])add(q[a1[i]][b1[i]],q[a2[i]][b2[i]]); if(in[q[a1[i]][b1[i]]] == in[q[a2[i]][b2[i]]] && q[a1[i]][b1[i]] < q[a2[i]][b2[i]]) add(q[a1[i]][b1[i]],q[a2[i]][b2[i]]); if(in[q[a1[i]][b1[i]]] == in[q[a2[i]][b2[i]]] && q[a2[i]][b2[i]] < q[a1[i]][b1[i]]) add(q[a2[i]][b2[i]],q[a1[i]][b1[i]]); h[q[a1[i]][b1[i]]][q[a2[i]][b2[i]]] = h[q[a2[i]][b2[i]]][q[a1[i]][b1[i]]] = 1; } long long ans = 0; for(int k = 1;k <= n;k += 1) { for(int i = head[k];i;i = e[i].next) { int v = e[i].v; vis[v] = k; } for(int i = head[k];i;i = e[i].next) { int v = e[i].v; for(int r = head[v];r;r = e[r].next) { int u = e[r].v; //cout << k << v << u << endl; if(vis[u] == k) { if(!rui(d[k][v],d[v][u],d[k][u]))continue; long long s = gets(d[k][v],d[v][u],d[k][u]); ans += (s - (w[k][v] + w[v][u] + w[k][u]) / 2 + 1) * h[k][u] * h[k][v] * h[v][u]; ans %= mod; } } } } cout << ans << endl; return 0; }
D2T1
问题转化,求出一种方案使得这个新图存在一个环并且所有点联通,我们再把问题细化, 所有点联通是个啥!最小生成树!咋样存在环?连一条不在树中最小边!!! //挂题原因 小字没看见呜呜呜呜(论我到底有多粗心) //没有存在感的分割线 code: 代码搁机房了嘤嘤嘤
D2T2
满分算法还没搞懂(待更新)
D2T3
现场,聪聪贪心拿了40,但是正解的贪心还没调出来(待更新,可能是我菜了吧)