\(D1T1\) 潜伏者 \((OK)\)
\(D1T3\) 最优贸易 \((OK)\)
\(D1T4\) 靶形数独 \((OK)\)
这四道之前都做过,所以再做一次还是挺快的.
\(T1\)字符串模拟题,不想讲,不难.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=105;
int a[N],b[N];
char s1[N],s2[N],s3[N];
int main(){
scanf("%s%s%s",s1+1,s2+1,s3+1);
int n=strlen(s1+1),m=strlen(s2+1);
if(n!=m){puts("Failed");return 0;}
for(int i=1;i<=n;++i){
if(a[s1[i]-'A'+1]!=0&&a[s1[i]-'A'+1]!=s2[i]-'A'+1){
puts("Failed");return 0;
}
if(b[s2[i]-'A'+1]!=0&&b[s2[i]-'A'+1]!=s1[i]-'A'+1){
puts("Failed");return 0;
}
a[s1[i]-'A'+1]=s2[i]-'A'+1;
b[s2[i]-'A'+1]=s1[i]-'A'+1;
}
for(int i=1;i<=26;++i)
if(!a[i]){puts("Failed");return 0;}
int k=strlen(s3+1);
for(int i=1;i<=k;++i){
printf("%c",(char)(a[s3[i]-'A'+1]-1+'A'));
}printf("\n");
return 0;
}
\(T2\)暴力就可以水过去,因为\(lcm(x,c)=d\),所以\(x\)一定是\(d\)的约数,所以\(O(\sqrt d)\)枚举\(d\)的所有约数,然后同时对那两个式子进行判断是否合法即可.
第一个\(gcd(x,a)=b\)可以直接判断,然后对于第二个\(lcm(x,c)=d\),因为\(gcd(x,y)*lcm(x,y)=x*y\),所以有\(d=\frac{x*c}{gcd(x,c)}\),判断这个式子即可.
其实这样做的理论时间复杂度是\(n\sqrt dlog_d\),对于\(n<=2000,d<=2e9\)来说是等于\(831909413\),然后因为肯定跑不满,所以本题才能水过去.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline ll read(){
ll x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
inline ll gcd(ll a,ll b){
if(!b)return a;
return gcd(b,a%b);
}
int main(){
int n=read();
while(n--){
ll a=read(),b=read(),c=read(),d=read(),ans=0;
for(int i=1;i*i<=d;++i){
if(d%i==0){
ll x=i;
if(gcd(a,x)==b){
if((c*x)/gcd(c,x)==d)++ans;
}
if(i*i!=d){
x=d/i;
if(gcd(a,x)==b){
if((c*x)/gcd(c,x)==d)++ans;
}
}
}
}
printf("%lld\n",ans);
}
return 0;
}
\(T3\)建正图跑一次\(spfa/dij\),记录\(minn[i]\)表示\(1\)号节点到节点\(i\)的路径中的最小买进价格,然后建反图跑一次\(spfa/dij\),记录\(maxn[i]\)表示节点\(n\)到节点\(i\)的路径中的最大卖出价格.最后扫描所有节点,取最大的\(maxn[i]-minn[i]\)即可.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=1e5+5;
const int M=5e5+5;
int n,m,ans,a[M],b[M],c[M];
int val[N],visit[N],minn[N],maxn[N];
int tot,head[N],nxt[M<<1],to[M<<1];
queue<int>q;
inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
int main(){
n=read();m=read();
for(int i=1;i<=n;++i)val[i]=read();
for(int i=1;i<=m;++i){
a[i]=read(),b[i]=read();c[i]=read();
add(a[i],b[i]);if(c[i]==2)add(b[i],a[i]);
}
q.push(1);visit[1]=1;memset(minn,0x3f,sizeof(minn));minn[1]=val[1];
while(q.size()){
int u=q.front();q.pop();visit[u]=0;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(minn[v]>min(minn[u],val[v])){
minn[v]=min(minn[u],val[v]);
if(!visit[v])visit[v]=1,q.push(v);
}
}
}
tot=0;memset(head,0,sizeof(head));
for(int i=1;i<=m;++i){add(b[i],a[i]);if(c[i]==2)add(a[i],b[i]);}
q.push(n);visit[n]=1;maxn[n]=val[n];
while(q.size()){
int u=q.front();q.pop();visit[u]=0;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(maxn[v]<max(maxn[u],val[v])){
maxn[v]=max(maxn[u],val[v]);
if(!visit[v])visit[v]=1,q.push(v);
}
}
}
for(int i=1;i<=n;++i)ans=max(ans,maxn[i]-minn[i]);
printf("%d\n",ans);
return 0;
}
\(T4\)就只有一个剪枝:优化搜索顺序.每一次从状态量最少的行开始搜,这个可以预处理.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
int a[10][10],hang[10][10],lie[10][10],ge[10][10];
int now,ans,tot,dfs[100][5];
struct node{int num,sum;}line[10];
inline bool cmp(node x,node y){return x.sum<y.sum;}
inline int calc(int i,int j){return (i-1)/3*3+(j-1)/3+1;}
inline int point(int x,int y){
if(x==5&&y==5)return 10;
if(x>=4&&x<=6&&y>=4&&y<=6)return 9;
if(x>=3&&x<=7&&y>=3&&y<=7)return 8;
if(x>=2&&x<=8&&y>=2&&y<=8)return 7;
return 6;
}
inline void DFS(int ord,int has){
if(ord>tot){
if(has>ans)ans=has;
return;
}
for(int i=1;i<=9;++i){
if(hang[dfs[ord][1]][i])continue;
if(lie[dfs[ord][2]][i])continue;
if(ge[dfs[ord][3]][i])continue;
hang[dfs[ord][1]][i]=1;
lie[dfs[ord][2]][i]=1;
ge[dfs[ord][3]][i]=1;
DFS(ord+1,has+dfs[ord][4]*i);
hang[dfs[ord][1]][i]=0;
lie[dfs[ord][2]][i]=0;
ge[dfs[ord][3]][i]=0;
}
}
int main(){
for(int i=1;i<=9;++i)line[i].num=i;
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j){
a[i][j]=read();
if(!a[i][j]){++line[i].sum;continue;}
hang[i][a[i][j]]=1;
lie[j][a[i][j]]=1;
ge[calc(i,j)][a[i][j]]=1;
now+=point(i,j)*a[i][j];
}
sort(line+1,line+9+1,cmp);
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j){
if(a[line[i].num][j])continue;
dfs[++tot][1]=line[i].num;
dfs[tot][2]=j;
dfs[tot][3]=calc(line[i].num,j);
dfs[tot][4]=point(line[i].num,j);
}
DFS(1,now);if(!ans)puts("-1");else printf("%d\n",ans);
return 0;
}