19 南京站+div2思维
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19 南京站+div2思维相关的知识,希望对你有一定的参考价值。
D. Meta-set
题意:给定一段长为k的数字组合,每个数组的选取为0,1,2。找到三个组合满足每位上的k都相同或者都不相同可称为1队,对于5个组合组成的meta-set,要求其中对数要大于等于2.
思路:
1.可发现每两个组合可确定一个唯一的组合,围绕着这个组合可产生多对meta-set。
2.进一步发现以自己为中心的组合meta-set的个数为x*(x-1)/2
.
3.接着就是代码的处理。我是将每个组合变成字符串存了起来,用vector也可以。
思维误区:
开始认为组合的中心是已知的,采用O(n2 )循环,从每个组合开始记录有多少满足条件的对数,
再取C(n,2)累加结果。这是错误的,因为这个组合不作为中心时,可作为边缘加入到其他中心的组合中。
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define eps 1e-7
using namespace std;
int n,k,s[1005][25];
map<string,int>mp,mm;
void solve()
cin>>n>>k;
for(int i=1;i<=n;i++)
string ss="";
for(int j=1;j<=k;j++)
cin>>s[i][j];ss+='0'+s[i][j];
mp[ss]=i;
int ans=0;
for(int i=1;i<=n;i++)
int tmp=0;
for(int j=i+1;j<=n;j++)
string ss="";
for(int g=1;g<=k;g++)
if(s[i][g]==s[j][g]) ss+='0'+s[i][g];
else ss+='0'+(3-s[i][g]-s[j][g]);
mm[ss]++;
/*
if(mp[ss]&&mp[ss]>j)
for(int g=1;g<=k;g++) cout<<s[i][g]<<" ";
cout<<"gg";
for(int g=1;g<=k;g++) cout<<s[j][g]<<" ";
cout<<"kkk "<<ss<<endl;
tmp++;
*/
for(int i=1;i<=n;i++)
string ss="";
for(int j=1;j<=k;j++) ss+='0'+s[i][j];
ans+=(mm[ss]-1)*mm[ss]/2;
cout<<ans<<endl;
signed main()
//int T;cin>>T;
//while(T--)
solve();
return 0;
C. Digital Path
去掉注释可跟踪代码的执行。
思路:
1.正常考虑一个点,他可能不是终点,也不是起点,若从它开始向两端深搜,不太可能。
2.换个想法,从终点开始搜索,周围没有比他大的数,开始深搜。
记忆化方程dp[x][y][len]含义:到达x行y列路径长度为len的方案数。若长度>=4,则都记录为4
转移方程:dp[x][y][len]+=dp[nx][ny][len-1]
,搜索数字比他小1的方格,可由它转移而来
dp[x][y][4]+=dp[nx][ny][4]
,到达相邻格子的也并非为正好为4
3.若len=1,并且可作为一条路径的起点,则dp[x][y][1]=1
,否则为0.
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define eps 1e-7
using namespace std;
const int mod=1e9+7;
int n,m,a[1005][1005],dp[1005][1005][5];
bool vis[1005][1005];
int dx[5]=0,1,-1,0,0;
int dy[5]=0,0,0,-1,1;
//判终点
int ch1(int x,int y)
for(int i=1;i<=4;i++)
int nx=x+dx[i],ny=y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[x][y]==a[nx][ny]-1) return 0;
return 1;
//判起点
int ch2(int x,int y)
for(int i=1;i<=4;i++)
int nx=x+dx[i],ny=y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&a[x][y]==a[nx][ny]+1) return 0;
return 1;
int dfs(int x,int y,int len)
if(len==1)
if(ch2(x,y)) dp[x][y][len]=1; else dp[x][y][len]=0;
//cout<<x<<" "<<y<<" "<<len<<" "<<dp[x][y][len]<<endl;
return dp[x][y][len];
if(dp[x][y][len]!=-1) return dp[x][y][len];
int tmp=0;
for(int i=1;i<=4;i++)
int nx=dx[i]+x,ny=dy[i]+y;
if(nx<1||nx>n||ny<1||ny>m||a[x][y]!=a[nx][ny]+1) continue;
tmp=(tmp+dfs(nx,ny,len-1))%mod;
if(len==4)
//cout<<nx<<" "<<ny<<endl;
tmp=(tmp+dfs(nx,ny,len))%mod;
dp[x][y][len]=tmp%mod;
//cout<<x<<" "<<y<<" "<<len<<" "<<dp[x][y][len]<<endl;
return dp[x][y][len];
void solve()
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++) for(int k=0;k<5;k++) dp[i][j][k]=-1;
int ans=0;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
if(a[i][j]!=-1&&ch1(i,j))
//cout<<"gg"<<endl;
ans=(ans+dfs(i,j,4))%mod;
cout<<ans<<endl;
signed main()
ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
K. Triangle
看了2个多小时,之前没怎么做过计算几何的题目,本题思路不难,但代码的实现挺难的。这次算积累了一套计算几何的板子,可算距离、点积、叉积、记录直线,判断点在线上(两个条件)
采用向量的方式,不需要考虑斜率不存在的情况。
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
using namespace std;
const int mod=1e9+7;
const double eps=1e-8;
double x[5],y[5];
struct Point
double x,y;
Point();
Point(double xx,double yy)x=xx,y=yy;
Point operator -(Point B)
return Point(x-B.x,y-B.y);
p[5],pos[5];
struct Line
Point p1,p2;
Line();
Line(Point p11,Point p22)p1=p11,p2=p22;
lin[5];
int sgn(double x)
if(abs(x)<eps) return 0;
return x<0?-1:1;
double dis(Point p1,Point p2)
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
double cross(Point p1,Point p2)
return p1.x*p2.y-p1.y*p2.x;
double dot(Point p1,Point p2)
return p1.x*p2.x+p1.y*p2.y;
int Pt_on_Line(Point p,Line ln)
return sgn(cross(p-ln.p1,ln.p1-ln.p2))==0&&sgn(dot(p-ln.p1,p-ln.p2))<=0;
void solve()
for(int i=1;i<=4;i++) cin>>p[i].x>>p[i].y;
lin[1]=Line(p[1],p[2]);lin[2]=Line(p[1],p[3]);lin[3]=Line(p[2],p[3]);
if(Pt_on_Line(p[4],lin[1])==0&&Pt_on_Line(p[4],lin[2])==0&&Pt_on_Line(p[4],lin[3])==0)
cout<<-1<<endl;return;
int g=0;
for(int i=1;i<=3;i++)
if(Pt_on_Line(p[4],lin[i])==1) g=i;break;
if(g==1) pos[1]=p[3];else if(g==2) pos[1]=p[2];else pos[1]=p[3];
if(dis(p[4],lin[g].p1)>=dis(p[4],lin[g].p2))
pos[2]=lin[g].p1,pos[3]=lin[g].p2;
else
pos[2]=lin[g].p2,pos[3]=lin[g].p1;
double tmp=(dis(pos[2],pos[3])/dis(pos[2],p[4]))*0.5;
double dx=pos[2].x+tmp*(pos[1].x-pos[2].x);
double dy=pos[2].y+tmp*(pos[1].y-pos[2].y);
cout<<fixed<<setprecision(12)<<dx<<" "<<dy<<endl;
signed main()
ios;
int T;cin>>T;
while(T--)
solve();
return 0;
以上是关于19 南京站+div2思维的主要内容,如果未能解决你的问题,请参考以下文章
2018 ACM-ICPC 南京站 E Eva and Euro coins (思维)
CF#468 div2 D. Peculiar apple-tree(思维)