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;
}