\(T1\ crime\)
计算几何\(+\)最短路,我的写法很麻烦
比较无脑,直接扫一遍判断能否连接即可,需要特别判断对角线的情况
#include<bits/stdc++.h>
#define double long double
#define MAXN 200005
using namespace std;
const double g=9.80665,eps=1e-6,addx=1e-10;
int head[MAXN],nxt[MAXN<<1],to[MAXN<<1],tot;
int dis[MAXN],h[25][25];
int dx,dy,w,v,lx,ly;
void put(double x)
{
printf("%.3f\n",x);
}
bool ck(int x,int y,int xx,int yy,double Sx,double Sy,double t)
{
double Vx=Sx/t;
double Vy=(Sy+0.5*g*t*t)/t;
if(x>xx)
{
double Sumx=sqrt(1.0*abs(x-xx)*w*abs(x-xx)*w);
double Sumy=sqrt(1.0*abs(y-yy)*w*abs(y-yy)*w);
for(int i=x;i>xx;i--)
{
double disx=(x-i)*w*1.0+0.5*w;
double disy=disx/Sumx*Sumy;
double nowy=(y-1)*w+0.5*w+(yy>y?1:(yy==y?0:-1))*disy+addx;
int id=(ceil)(nowy/w);
double nowt=sqrt(pow(disx,2)+pow(disy,2))/Vx;
double peoh=h[x][y]+Vy*nowt-0.5*g*nowt*nowt;
double zah;
if(fabs(1.0*(id-1)*w-nowy)<eps)
{
zah=1.0*max({h[i][id],h[i][id-1],h[i-1][id],h[i-1][id-1]});
}
else
{
zah=1.0*max(h[i][id],h[i-1][id]);
}
if(peoh<zah) return false;
}
}
if(x<xx)
{
double Sumx=sqrt(1.0*abs(x-xx)*w*abs(x-xx)*w);
double Sumy=sqrt(1.0*abs(y-yy)*w*abs(y-yy)*w);
for(int i=x;i<xx;i++)
{
double disx=(i-x)*w*1.0+0.5*w;
double disy=disx/Sumx*Sumy;
double nowy=(y-1)*w+0.5*w+(yy>y?1:(yy==y?0:-1))*disy+addx;
int id=(ceil)(nowy/w);
double nowt=sqrt(pow(disx,2)+pow(disy,2))/Vx;
double peoh=h[x][y]+Vy*nowt-0.5*g*nowt*nowt;
double zah;
if(fabs(1.0*(id-1)*w-nowy)<eps)
{
zah=1.0*max({h[i][id],h[i][id-1],h[i+1][id],h[i+1][id-1]});
}
else
{
zah=1.0*max(h[i][id],h[i+1][id]);
}
if(peoh<zah) return false;
}
}
if(y>yy)
{
double Sumx=sqrt(1.0*abs(x-xx)*w*abs(x-xx)*w);
double Sumy=sqrt(1.0*abs(y-yy)*w*abs(y-yy)*w);
for(int i=y;i>yy;i--)
{
double disy=(y-i)*w*1.0+0.5*w;
double disx=(disy/Sumy)*Sumx;
double nowx=(x-1)*w+0.5*w+(xx>x?1:(xx==x?0:-1))*disx+addx;
int id=(ceil)(nowx/w);
double nowt=sqrt(pow(disx,2)+pow(disy,2))/Vx;
double peoh=h[x][y]+Vy*nowt-0.5*g*nowt*nowt;
double zah;
if(fabs(1.0*(id-1)*w-nowx)<eps)
{
zah=max({h[id][i],h[id-1][i],h[id][i-1],h[id-1][i-1]});
}
else
{
zah=max(h[id][i],h[id][i-1]);
}
if(peoh<zah) return false;
}
}
if(y<yy)
{
double Sumx=sqrt(1.0*abs(x-xx)*w*abs(x-xx)*w);
double Sumy=sqrt(1.0*abs(y-yy)*w*abs(y-yy)*w);
for(int i=y;i<yy;i++)
{
double disy=(i-y)*w*1.0+0.5*w;
double disx=(disy/Sumy)*Sumx;
double nowx=(x-1)*w+0.5*w+(xx>x?1:(xx==x?0:-1))*disx+addx;
int id=(ceil)(nowx/w);
double nowt=sqrt(pow(disx,2)+pow(disy,2))/Vx;
double peoh=h[x][y]+Vy*nowt-0.5*g*nowt*nowt;
double zah;
if(fabs(1.0*(id-1)*w-nowx)<eps)
{
zah=max({h[id][i],h[id-1][i],h[id][i+1],h[id-1][i+1]});
}
else
{
zah=max(h[id][i],h[id][i+1]);
}
if(peoh<zah) return false;
}
}
return true;
}
bool check(int x,int y,int xx,int yy)
{
double Sx=sqrt(pow((abs(x-xx)*w),2)+pow((abs(y-yy)*w),2));
double Sy=h[xx][yy]-h[x][y];
double det=pow(v*v-g*Sy,2)-g*g*Sy*Sy-g*g*Sx*Sx;
if(det<0) return false;
double t1=sqrt((v*v-Sy*g+sqrt(det))/(0.5*g*g));
double t2=sqrt((v*v-Sy*g-sqrt(det))/(0.5*g*g));
return ck(x,y,xx,yy,Sx,Sy,t1)|ck(x,y,xx,yy,Sx,Sy,t2);
}
int id(int x,int y)
{
return (x-1)*dy+y;
}
void add(int u,int v)
{
tot++;
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
void bfs()
{
queue<int>q;
memset(dis,-1,sizeof(dis));
q.push(id(lx,ly));
dis[id(lx,ly)]=0;
while(q.size())
{
int now=q.front();
q.pop();
for(int i=head[now];i;i=nxt[i])
{
int y=to[i];
if(dis[y]==-1)
{
dis[y]=dis[now]+1;
q.push(y);
}
}
}
}
int main()
{
scanf("%d%d%d%d%d%d",&dx,&dy,&w,&v,&lx,&ly);
for(int i=1;i<=dy;i++)
{
for(int j=1;j<=dx;j++)
{
scanf("%d",&h[j][i]);
}
}
for(int i=1;i<=dy;i++)
{
for(int j=1;j<=dx;j++)
{
for(int i1=1;i1<=dy;i1++)
{
for(int j1=1;j1<=dx;j1++)
{
if(i==i1&&j==j1) continue;
if(check(j,i,j1,i1))
{
add(id(j,i),id(j1,i1));
}
}
}
}
}
bfs();
for(int i=1;i<=dy;i++)
{
for(int j=1;j<=dx;j++)
{
if(dis[id(j,i)]==-1) cout<<"X ";
else cout<<dis[id(j,i)]<<" ";
}
cout<<"\n";
}
}
\(T2\ circle\)
猜结论的二次剩余题 \(kill\ me\)
这道题是一个纯纯的结论题
\(bz\)掏出了三个结论:
\(Sit_1:\)
\[x^2+y^2\equiv r\mod p
\]
我们记 \(Num(r,p)\)
\[p=\prod p_i^{k_i}
\\
Num(r,p)=\prod\limits_{}^i Num(r,p_i)
\]
其实考场上靠直觉能猜到的
\(Sit_2:\)
\(r\ne 0\) 值一样,可以打个表观察一下
\[Num(r,p)=\frac{p\times p-Num(0,p)}{p-1}
\]
\(Sit_3:\)
如果 \(-1\) 有在\(\mod p\)二次剩余 \(Num(0,p)=2\times p-1\)
否则 \(Num(0,p)=1\)
一般这种结论题代码都比较简单了
#include<bits/stdc++.h>
#define int long long
#define MAXN 10000005
using namespace std;
int pri[MAXN+5],val[MAXN+5],Mp[MAXN+5],cnt,p,r;
bool vis[MAXN+5];
int my_pow(int a,int b,int p)
{
int res=1;
while(b)
{
if(b&1)
{
res=(res*a)%p;
}
a=(a*a)%p;
b>>=1;
}
return res;
}
void Init()
{
for(int i=2;i<=MAXN;i++)
{
if(!vis[i])
{
pri[++cnt]=i;
if(my_pow(i-1,(i-1)/2,i)==1) val[i]=(2*i-1);
else val[i]=1;
Mp[i]=i;
}
for(int j=1;j<=cnt&&i*pri[j]<=MAXN;j++)
{
vis[i*pri[j]]=true;
Mp[i*pri[j]]=max(Mp[i],pri[j]);
if(i%pri[j]==0) break;
}
}
}
int Num(int r,int p)
{
if(r==0) return val[p];
return (p*p-val[p])/(p-1);
}
// 1 5 0
int dfs(int now)
{
if(now==1) return 1;
int x=now,pr=Mp[now];
while(x%pr==0) x/=pr;
return Num(r%Mp[now],Mp[now])*dfs(x);
}
void sol()
{
scanf("%lld%lld",&p,&r);
cout<<dfs(p)<<"\n";
}
int T;
signed main()
{
scanf("%lld",&T);
Init();
while(T--) sol();
}
\(T3\ crystal\)
和曾经的一道\(CF\)的题有点像
\(\mod 998244353\) 其实感觉像是在提示误导 \(FWT\)
\(a\oplus b=c,a\oplus c=b1\)
我们前\(n-1\)个数任选都不能大于最后选的数的 \(m\) 的话,就可以直接乘法原理了
这就和 \(CF\) 那道题先解除一些数位的限制一样。
考虑,枚举 \(a_p\) 和 \(m_p\) 的最短 \(LCP\), 然后我们这个数系数为 \(1\),其余的数系数相乘即可
具体的,我们只需要让第 \(i\) 位是 \(0\),并且有一个位置 \(p\),\(a_p\) 的第 \(i\) 位是 \(1\) 就可以统计答案了
\(dp[j][k][l]\) 表示第 \(j\) 个数,第 \(i\) 位异或起来为 \(k\) ,有没有钦定 \(p\) 的方案数
考虑 \(m_j\) 第 \(i\) 位为 \(1\),\(a_j\) 可以选 \(0/1\),选 \(0\) 的话贡献的系数是 \(2^i\) ,选 \(1\) 贡献的系数是 \(m\& (2^i-1)+1\),如果确定这一位的话,系数是 \(1\)
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define MAXN 200005
using namespace std;
const int mod=998244353;
int n,Ans,dat[MAXN];
int dp[2][2][2];
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&dat[i]);
Ans^=dat[i];
}
Ans=!Ans;
int Xor=0;
for(int i=31;i>=0;i--)
{
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
for(int j=1;j<=n;j++)
{
int now=(j&1);
int pre=(now^1);
Xor^=(dat[j]>>(i+1));
if(dat[j]>>i&1)
{
for(int k=0;k<=1;k++)
{
for(int l=0;l<=1;l++)
{
(dp[now][k^1][l]=dp[pre][k][l]*((dat[j]&(1<<i)-1)+1)%mod)%=mod;
}
}
for(int k=0;k<=1;k++)
{
(dp[now][k][1]+=dp[pre][k][0]+(ull)(dp[pre][k][1]<<i)%mod)%=mod;
}
}
else
{
for(int k=0;k<=1;k++)
{
for(int l=0;l<=1;l++)
{
(dp[now][k][l]=dp[pre][k][l]*((dat[j]&(1<<i)-1)+1)%mod)%=mod;
}
}
}
}
if(Xor) continue;
//3 1 2 3
Ans=(Ans+dp[n&1][0][1])%mod;
}
cout<<Ans<<"\n";
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章