[游记]2022年多校冲刺NOIP联训测试7-2022.7.28
作者:互联网
好吧今天算是没有挂分然后考得还不错?
得到了 $300/400$ 分,排名第七
终于能截上我了(
A. 计算器
B. 对称轴
C. 互质
D. 签到题
这个评测机是真的玄学 $\cdots\cdots$
A. 计算器
这,一眼看到数据范围 $n\leqslant 50$
大概率是个暴力了
于是就先写了一个普通的,发现大样例跑得很慢
发现有些时候 $k$ 不是连续的,这样造成了最多会有 $n$ 的无法接受的常数
所以我们需要进行一个去重再爆搜,如果评测机开心会给到 $100$ 分,像我这种脸黑的人就只能拿到 $80$ 分
更离谱的是中午我来机房交了一遍原代码
他就 $\mathfrak{\color{green}{AC}}$ 了
这就是评测机波动么
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #define int long long #define WR WinterRain using namespace std; const int WR=100100,INF=2147483647; struct Equipment{ int id; int a,b,c,d; }equ[WR]; int n,k; int prt[100][100],cnt[100]; int tmp[100]; int maxx; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } bool cmp(Equipment x,Equipment y){ return x.id<y.id; } void dfs(int x,int suma,int sumb,int sumc,int sumd){ if(x>k||cnt[x]==0){ maxx=max(maxx,(100+suma)*(100+sumb)*(100+sumc)*(100+sumd)); return; } for(int i=1;i<=cnt[x];i++) dfs(x+1,suma+equ[prt[x][i]].a,sumb+equ[prt[x][i]].b, sumc+equ[prt[x][i]].c,sumd+equ[prt[x][i]].d); } signed main(){ n=read(),k=read(); for(int i=1;i<=n;i++){ equ[i].id=tmp[i]=read(); equ[i].a=read(),equ[i].b=read(),equ[i].c=read(),equ[i].d=read(); } sort(equ+1,equ+1+n,cmp); sort(tmp,tmp+1+n); int tot=unique(tmp+1,tmp+1+n)-tmp-1; for(int i=1;i<=n;i++) equ[i].id=lower_bound(tmp+1,tmp+1+tot,equ[i].id)-tmp; for(int i=1;i<=n;i++) prt[equ[i].id][++cnt[equ[i].id]]=i; dfs(1,0,0,0,0); printf("%lld\n",maxx); return 0; }WR的程序
#include<cstdio> typedef long long ll; const int N=55; int Case,n,m,i,j,x,cnt[N],nxt[N],e[N][N][4];ll ans; void dfs(int x,int a,int b,int c,int d){ if(x>m){ ll tmp=1LL*a*b*c*d; if(tmp>ans)ans=tmp; return; } int num=cnt[x]; if(!num){ dfs(nxt[x],a,b,c,d); return; } for(int i=1;i<=num;i++)dfs(x+1,a+e[x][i][0],b+e[x][i][1],c+e[x][i][2],d+e[x][i][3]); } int main(){ Case=1; while(Case--){ scanf("%d%d",&n,&m); for(i=1;i<=m;i++)cnt[i]=0; while(n--){ scanf("%d",&x); cnt[x]++; for(j=0;j<4;j++)scanf("%d",&e[x][cnt[x]][j]); } x=m+1; for(i=m;i;i--){ nxt[i]=x; if(cnt[i])x=i; } ans=0; dfs(1,100,100,100,100); printf("%lld\n",ans); } }std
B. 对称轴
一眼计算几何直接再见
后来打完暴力回来再看发现也不是那么不可做
于是尝试了一个有趣的解法
考虑上面的一张图,显然 $y=x$ 是原三角形的唯一一个对称轴
那么从 $(0,0)$ 开始,按照顺时针遍历角和边可以得到一个序列 $$1,45^\circ,\sqrt{2},45^\circ,1,90^\circ$$
看上去没有任何规律,但是我们可以试着把它再复制一遍,得到
$$1,45^\circ,\sqrt{2},45^\circ,1,90^\circ,1,45^\circ,\sqrt{2},45^\circ,1,90^\circ$$
注意到有两个部分(一部分刷红,一部分刷蓝)
$$\color{red}{1,45^\circ,\sqrt{2},45^\circ,1},90^\circ,1,45^\circ,\sqrt{2},45^\circ,1,90^\circ$$
$$1,45^\circ,\sqrt{2},\color{blue}{45^\circ,1,90^\circ,1,45^\circ},\sqrt{2},45^\circ,1,90^\circ$$
是回文的
我们还惊讶地发现,如果设角对应点,边长对应边
那么 $90^\circ$ 和 $\sqrt(2)$ ,也就是两个回文串的中心恰好是对称轴经过的点
不妨感性理解:我们以对称轴与多边形的交点为断点,那么拉直多边形,显然会形成一个回文串
接着我们考虑怎样计算所谓的回文序列
因为直接算会出现根号,角度也很难表示
根号的话考虑平方消掉,角度可以化成两个向量间的点积/叉积
这里我更倾向于使用叉积,可能是受到高数荼毒的原因(
不妨设第一个点为 $A(x_1,y_1)$ ,第二个 $B(x_2,y_2)$ ,第三个 $C(x_3,y_3)$
$\overrightarrow{A B}=(x_2-x_1,y_2-y_1)$ ,$\overrightarrow{B C}=(x_3-x_2,y_3-y_2)$
那么 $\overrightarrow{A B}\times \overrightarrow{B C} = \begin{vmatrix} \vec{i} & \vec{j} &\vec{k} \\ x_2-x_1 & y_2-y_1 & 0 \\ x_3-x_2 & y_3-y_2 & 0 \end{vmatrix} = [(x_2-x_1)(x_3-x_2)-(y_2-y_1)(y_3-y_2)]\vec{k}$
拆环成链判断回文即可,最后答案记得除以 $2$
一个玄学的地方是哈希判断回文居然没有暴力快???离谱离谱
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #define int long long #define WR WinterRain using namespace std; const int WR=400100,INF=2147483647,base=233; struct Node{ int x,y; }a[WR]; // struct Hash_Table{ // unsigned int hash[WR],pw[WR]; // void init(){ // pw[0]=1; // for(int i=1;i<WR;i++) pw[i]=pw[i-1]*base; // } // unsigned int queryfor(int l,int r){ // return hash[r]-hash[l-1]*pw[r-l+1]; // } // unsigned int querybck(int l,int r){ // return hash[l]-hash[r+1]*pw[r-l+1]; // } // }hshfor,hshbck; int str[WR]; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } // bool judge(int l,int r){ // if(hshfor.queryfor(l,r)==hshbck.querybck(l,r)) return true; // else return false; // } signed main(){ int t=read(); // hshfor.init(),hshbck.init(); while(t--){ int ans=0; int n=read(); for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); for(int i=1;i<=n;i++){ int p=i,q=i+1,r=i+2; if(q>n) q%=n; if(r>n) r%=n; str[(i<<1)-1]=(a[p].x-a[q].x)*(a[p].x-a[q].x) +(a[p].y-a[q].y)*(a[p].y-a[q].y); str[(i<<1)]=(a[p].x-a[q].x)*(a[q].y-a[r].y) -(a[p].y-a[q].y)*(a[q].x-a[r].x); } for(int i=1;i<=(n<<1);i++) str[i+(n<<1)]=str[i]; // for(int i=1;i<=(n<<2);i++) hshfor.hash[i]=hshfor.hash[i-1]*base+str[i]; // for(int i=(n<<2);i>=1;i--) hshbck.hash[i]=hshbck.hash[i+1]*base+str[i]; for(int i=1;i<=(n<<1);i++){ bool flag=true; for(int j=i;j<=i+(n<<1);j++){ if(str[j]!=str[(i+(n<<1))+1-j]){ flag=false; break; } } if(flag) ans++; //if(judge(i,i+(n<<1))) ans++; } printf("%lld\n",ans/*/2*/); } return 0; }View Code
标签:NOIP,int,45,28,circ,联训,WR,100,include 来源: https://www.cnblogs.com/WintersRain/p/16529406.html