逆元
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn = 50050; const int maxm = 32; const ll inf = 1e9; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<='9')) { if(ch=='-')f=-1; ch=getchar(); }; while(ch>='0'&&ch<='9') { x=x*10+(ch-'0'); ch=getchar(); }; return x*f; } bool isp(ll p){ ll m = sqrt(p); for(ll i = 2;i <= m;i++){ if(p%i==0)return false; } return true; } ll q_mul(ll a,ll b,ll mod){ ll ans = 0; while(b){ if(b&1){ b--; ans = (ans + a) % mod; } b>>=1; a = (a + a) % mod; } return ans; } ll qpow(ll x,ll y,ll mod){ ll res = 1; while(y){ if(y&1) res=q_mul(res,x,mod); x=q_mul(x,x,mod); y>>=1; } return res; } ll getans(ll t){ ll p=2; for(ll i = t-1;i >= 2;i--){ if(isp(i)){ p=i; break; } } ll inv=0,ans=1; for(ll i = t-1;i >= p+1;i--){ inv = qpow(i,t-2,t); if(inv <= p) ans=q_mul(ans,inv,t); } return ans; } int main() { int T; cin>>T; while(T--){ ll a; a=read(); cout<<getans(a)<<endl; } return 0; }
树状数组维护,将每个插在排名对应的位置
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define ld long double #define fo(i,l,r) for(int i = l;i <= r;i++) #define fd(i,l,r) for(int i = r;i >= l;i--) #define mem(x) memset(x,0,sizeof(x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn = 200050; const int maxm = 32; const ll inf = 1e9; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<='9')) { if(ch=='-')f=-1; ch=getchar(); }; while(ch>='0'&&ch<='9') { x=x*10+(ch-'0'); ch=getchar(); }; return x*f; } int n,m; ll c[maxn*3],a[maxn],b[maxn],d[maxn*3]; ll lowbit(ll x){ return x&(-x);} ll SUM(int r,ll *c){//区间查询 ll sum=0; for(int i=r;i;i-=lowbit(i)) sum+=c[i]; return sum; } void change(int x,ll m,ll *c){ for(int i=x;i<=n;i+=lowbit(i)) c[i]+=m;}//单点修改 struct dat{ ll v; int p; friend bool operator < (dat a,dat b){ return a.v > b.v; } }dats[maxn]; int main() { int T; cin>>T; while(T--){ n=read(); m=read(); mem(c); mem(d); fo(i,1,n){ dats[i].p=i; dats[i].v=read(); a[i] = dats[i].v; } sort(dats+1,dats+1+n); fo(i,1,n){ b[dats[i].p] = i; } ll sum = 0; fo(i,1,n){ sum += a[i]; int lp = 0,rp = n,mid,ans=0; while(lp <= rp){ mid = (lp + rp) >> 1; if(sum-SUM(mid,c)<=m){ rp = mid - 1; ans = mid; }else{ lp = mid + 1; } } printf("%lld ",SUM(ans,d)); change(b[i],a[i],c); change(b[i],1,d); } putchar('\n'); } return 0; }
支配树https://blog.csdn.net/a710128/article/details/49913553
在dag上求类似的东西,用lca即可,最后用lca统计答案
#include<bits/stdc++.h> #define LL long long #define MEM(x,y) memset(x,y,sizeof(x)) #define MOD(x) ((x)%mod) #define mod 1000000007 #define pb push_back #define STREAM_FAST ios::sync_with_stdio(false) using namespace std; const int maxn = 2e5 + 7; int n, m, deg[maxn], rt, a[maxn], dep[maxn], val[maxn]; int f[maxn][20]; vector<int>E[maxn], G[maxn], T[maxn]; void BFS() { queue<int>q; rt = n + 1; for (int i = 1; i <= n; i++) if (!deg[i]){q.push(i); E[rt].pb(i); G[i].pb(rt);} int tot = 0; while (!q.empty()) { int u = q.front(); q.pop(); a[++tot] = u; for (int v : E[u]) if ((--deg[v]) == 0) q.push(v); } } int LCA(int x, int y) { if (dep[x] > dep[y]) swap(x, y); for (int i = 19; i >= 0; i--) if (dep[y] > dep[x] && dep[f[y][i]] >= dep[x]) y = f[y][i]; for (int i = 19; i >= 0; i--) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; return x == y ? x : f[x][0]; } int main() { int tt; scanf("%d", &tt); while (tt--) { scanf("%d%d", &n, &m); for (int i = 1; i <= n + 1; i++) { E[i].clear(); G[i].clear(); T[i].clear(); dep[i] = deg[i] = 0; } while (m--) { int u, v; scanf("%d%d", &u, &v); E[v].pb(u); G[u].pb(v); deg[u]++; } BFS(); dep[rt] = 1; for (int i = 1; i <= n; i++) { int u = a[i], fa = -1; for (int v : G[u]) fa = (fa == -1 ? v : LCA(fa, v)); dep[u] = dep[fa] + 1; f[u][0] = fa; T[fa].pb(u); for (int i = 1; i <= 19; i++) f[u][i] = f[f[u][i - 1]][i - 1]; } int q; scanf("%d", &q); while (q--) { int u, v; scanf("%d%d", &u, &v); int lca = LCA(u, v); printf("%d\n", dep[u] + dep[v] - dep[lca] - 1); } } return 0; }
二分+dp,检验的时候用线段树求特定范围最大值
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include <set> #include <queue> #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fo(i,l,r) for(int i = l;i <= r;i++) #define mem(x) memset(x,0,sizeof(x)) using namespace std; const int maxn = 200050; const ll inf = 1e9; ll read() { ll x=0,f=1; char ch=getchar(); while(!(ch>='0'&&ch<='9')) { if(ch=='-')f=-1; ch=getchar(); }; while(ch>='0'&&ch<='9') { x=x*10+(ch-'0'); ch=getchar(); }; return x*f; } int n,m,k; int rt; ll Max[maxn<<2]; ll a[maxn],b[maxn],c[maxn],d[maxn]; void pushup(int rt){ Max[rt] = max(Max[rt<<1],Max[rt<<1|1]); } void addval(int p,ll v,int l,int r,int rt){ if(l == r){ Max[rt] = v; return; } int m = (l+r)>>1; if(p <= m) addval(p,v,lson); else addval(p,v,rson); pushup(rt); } ll query_max(int L,int R,int l,int r,int rt){ if(L <= l && r <= R){ return Max[rt]; } int m = (l+r)>>1; ll ret = -inf; if(L <= m) ret = max(ret,query_max(L,R,lson)); if(R > m) ret = max(ret,query_max(L,R,rson)); return ret; } struct dat{ ll v; int p; friend bool operator < (dat a,dat b){ if(a.v!=b.v)return a.v < b.v; else return a.p > b.p; } }dats[maxn]; bool check(ll t){ mem(c); int sz = maxn<<2; fo(i,0,sz-1)Max[i] = -inf*(ll)maxn; addval(b[0]+1,0,1,n+1,1); fo(i,1,n){ int p = lower_bound(d,d+1+n,dats[b[i]].v-t) - d; if(p > n)continue; ll now = query_max(p+1,n+1,1,n+1,1)+1; addval(b[i]+1,now,1,n+1,1); if(now >= k) return true; } return false; } int main() { int T; cin>>T; while(T--){ n=read(); k=read(); fo(i,1,n){ a[i]=read(); c[i] = c[i-1]+a[i]; dats[i].v = c[i]; dats[i].p = i; } dats[0].v=dats[0].p=0; sort(dats,dats+1+n); m = 0; fo(i,0,n){ b[dats[i].p] = i; d[i] = dats[i].v; } ll lp = (ll)maxn*(-inf),rp = (ll)maxn*inf,mid,ans; while(lp <= rp){ mid = (lp + rp) >> 1; if(check(mid)){ ans = mid; rp = mid - 1; }else{ lp = mid + 1; } } printf("%lld\n",ans); } return 0; }