T1 无线网络发射器选址
先看数据范围,128*128?果断直接暴力模拟发射器的位置,但是在计算在(x-d,y-d)到(x+d,y+d)中的之和时要注意边界和范围。什么?代码呢?这么斯波的题自己去写。
T2 联合权值
这道题记得很早以前就做过。条件1如何解决是这道题的难点。如果直接对每个点进行判断能否抵达终点显然会超时的。那么既然我们要判断哪些点能到终点,为啥不从终点反着广搜一遍,看看终点能到哪些点呢?于是思路就显而易见了。将所有路径反向,从终点开始做一遍BFS标记出哪些点是可以作为合法路径,再做一遍spfa(其实貌似BFS也能过)就搞定了。
#include<bits/stdc++.h> #define N 200005 #define inf 0x3f3f3f3f using std::queue; struct Edge{ int v,nxt; }e[N],E[N]; int n,m,s,t; int head[N],tot; int h[N],tol; void AddEdge(int u,int v){ e[++tot]=(Edge){v,head[u]};head[u]=tot;//正向边 E[++tol]=(Edge){u,h[v]};h[v]=tol;//反向边 } int vis[N];//表示这个点能直接到达终点 int be[N];//if be[i]== true 表示i没有被删除 int tt; int dfs(int x,int f){//反向遍历 vis[x]=true; for(int i=h[x];i;i=E[i].nxt){//反向边 int to=E[i].v; if(to==f)continue; if(vis[to])continue; dfs(to,x); } } int init(){//删除不能存在于路径上的点 for(int i=1;i<=n;++i){ if(!vis[i])continue;bool flag=0; for(int j=head[i];j;j=e[j].nxt){ int to=e[j].v; if(!vis[to])flag=true; } if(!flag)be[i]=true; } } int dis[N]; int spfa(int s,int t){// 从起点到终点的最短路 memset(dis,0x3f,sizeof(dis)); memset(vis,false,sizeof(vis)); int top,to; dis[s]=0;queue<int>que;que.push(s);vis[s]=true; while(!que.empty()){ top=que.front(); que.pop(); for(int i=head[top];i;i=e[i].nxt){ to=e[i].v; if(!be[to])continue; int l; if(dis[top]+1<dis[to]){ dis[to]=dis[top]+1; if(!vis[to]){ vis[to]=true; que.push(to); } } } } return dis[t]; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ int u,v; scanf("%d%d",&u,&v); AddEdge(u,v); } scanf("%d%d",&s,&t); dfs(t,0); init(); int ans=spfa(s,t); if(ans==inf)ans=-1; printf("%d\n",ans); return 0; }
T3 解方程
狗比数学题。如果我们有个一元四次方程a0+a1x+a2x^2+a3x^4+a4x^4=0,那么其显然等于(x(x(xa4+a3)+a2)+a1)+a0=0。这就是一个叫做秦九韶的人提出的imba解法(这货是宋朝人!)。换句话讲,对于一个多项式,维护一个初始值为0的sum,每一次先加上当前的系数a,再自乘x,这个多项式如果和为0,则这是方程的一个解。但是这个a比较大(dark),高精度又容易被卡常,于是我们就可以先给a取模。这里我要介绍一个非常excited的素数:19260817,据信这个素数可以极大的优化程序的运行时间,通常为1s。
#include<bits/stdc++.h> #define maxn 105 #define MOD1 23333 #define MOD2 19260817 using namespace std; int n,m,a1[maxn],a2[maxn],vis[1000005]; vector<int>ans; void read(int pos){ char c=getchar(); int x1=0,x2=0,f=1; while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x1=(x1*10+c-'0')%MOD1; x2=(x2*10+c-'0')%MOD2; c=getchar(); } a1[pos]=x1*f; a2[pos]=x2*f; } int check(int f[],int x,int mod) { int y=0; for(int i=n;i>=0;i--) y=((long long)y*x+f[i])%mod; return (!y)? 1:0; } int main(){ freopen("equation.in","r",stdin); freopen("equation.out","w",stdout); scanf("%d%d",&n,&m); for(int i=0;i<=n;i++)read(i); for(int i=1;i<=MOD1;i++) if(check(a1,i,MOD1)) for(int j=i;j<=m;j+=MOD1) if(check(a2,j,MOD2)) vis[j]=1; for(int i=1;i<=m;i++) if(vis[i])ans.push_back(i); printf("%d\n",ans.size()); for(int i=0;i<ans.size();i++)printf("%d\n",ans[i]); return 0; }