D1:
T1:快速幂
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> #define LL long long using namespace std; LL n,m,k,x; inline LL quickpow(LL a,LL b){//a^b %n LL ans=1ll; while(b){ if(b&1)ans=ans*a%n; a=a*a%n; b>>=1; } return ans; } int main(){ //freopen("circle.in","r",stdin); //freopen("circle.out","w",stdout); scanf("%lld%lld%lld%lld",&n,&m,&k,&x); printf("%lld",(x%n+m*quickpow(10ll,k)%n)%n); return 0; }
T2:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> #include<map> #define LL long long using namespace std; const int maxn=1e5+5; const int P=99999997; int n; int a[maxn],b[maxn],to[maxn],ans; map<int ,int >pa; map<int ,int >pb; int sum[maxn]; inline int lowbit(int x){return x&(-x);} inline int query(int p){ int ans=0; while(p){ ans+=sum[p]; p-=lowbit(p); } return ans; } inline void modify(int p){ while(p<=n){ sum[p]++; p+=lowbit(p); } } int main(){ //freopen("match.in","r",stdin); //freopen("match.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); pa[a[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); pb[b[i]]=i; } sort(a+1,a+n+1); sort(b+1,b+n+1); /* 这里用到了排序不等式,(a-b)^2==a^2+b^2-2ab, 找到一个排列 s.t. -2ab max 自然想到排序不等式 正序和 <= 乱序和 <= 逆序和 */ for(int i=1;i<=n;i++){ to[ pa[a[i]] ]=pb[b[i]]; } memset(sum,0,sizeof(sum)); ans=0; for(int i=n;i;i--){//由于是相邻的两个火柴交换,直接求逆序对 ans=(ans+query(to[i]-1))%P; modify(to[i]); } printf("%d\n",ans); return 0; }
T3:
这题挺不好想,但是从部分分出发
30` && 60` 有向图两点间最小边最大,二分答案,O(q *log( m)* m )
但是其中填边的步骤可以省略,O(q*m)--------->kruscal 第一个使得两点联通的 边就是答案
100` 我们发现 每个询问都会填边太麻烦,然后我们想,推出两个性质
1:
如果该边是答案,那么他一定在该图的最大生成树中(反证法)
2:
如果该边是答案,那么两点联通 当且仅当 该边被添加(反证法)
于是就得到了满分算法,最大生成树+LCA最小边
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> #define LL long long using namespace std; const int maxn=1e4+5; const int maxm=5e4+5; struct Edge{ int u; int v; int w; const bool operator<(const Edge &x)const{return w<x.w;} inline void read(){ scanf("%d%d%d",&u,&v,&w); } }e[maxm]; int n,m,q; int father[maxn]; int find(int x){return father[x]==x ? x : father[x]=find(father[x]);}//dsu int fst[maxn],nxt[maxm<<1],to[maxm<<1],w[maxm<<1],edge_count; inline void add(int x,int y,int z){ edge_count++; to[edge_count]=y; w[edge_count]=z; nxt[edge_count]=fst[x]; fst[x]=edge_count; } inline void kruscal(){ for(int i=1;i<=n;i++)father[i]=i;//dsu_init sort(e+1,e+m+1); for(int i=m;i;i--){//鏈€澶х敓鎴愭爲 int fu=find(e[i].u);int fv=find(e[i].v); if(fu==fv)continue; father[fu]=fv; add(e[i].u,e[i].v,e[i].w); add(e[i].v,e[i].u,e[i].w); } } const int INF=0x3f3f3f3f; int f[maxn][50],g[maxn][50],deep[maxn],tre[maxn],temp; void dfs(int u,int fa){ tre[u]=temp; deep[u]=deep[fa]+1; for(int i=1;i<30;i++){ f[u][i]=f[ f[u][i-1] ][i-1]; g[u][i]=min(g[ f[u][i-1] ][i-1],g[u][i-1]); } for(int i=fst[u];i;i=nxt[i]){ int v=to[i]; if(v==fa)continue; f[v][0]=u; g[v][0]=w[i]; dfs(v,u); } } inline void LCA_init(){ memset(g,0x3f,sizeof(g)); for(int i=1;i<=n;i++)if(!deep[i]){ temp++; dfs(i,0); } } inline int LCA(int x,int y){ int ans=INF; if(deep[x]<deep[y])swap(x,y); for(int i=29;i>=0;i--){ if(deep[f[x][i]]>=deep[y]){ ans=min(ans,g[x][i]); x=f[x][i]; } } if(x==y)return ans; for(int i=29;i>=0;i--){ if(f[x][i]!=f[y][i]){ ans=min(ans,min(g[x][i],g[y][i])); x=f[x][i];y=f[y][i]; } } ans=min(ans,min(g[x][0],g[y][0])); return ans; } int main(){ //freopen("truck.in","r",stdin); //freopen("truck.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ e[i].read(); } kruscal(); LCA_init(); scanf("%d",&q); for(int i=1,x,y;i<=q;i++){ scanf("%d%d",&x,&y); if(tre[x]!=tre[y])printf("-1\n"); else printf("%d\n",LCA(x,y)); } return 0; }