多校 2009 3
D n 然后n个数 (1<=数<=n) 要求是变成序列1-n 按顺序 可以交换相邻2个数字a b 花费是 a+b 求最小花费
线段数维护 区间里的数的数目 然后区间的和 每个数 查询比他小的数目的个数和 他们的和 那么花费就是 数目 *a + sum long long
#include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> using namespace std; #define MAXN 100010 #define inf 1000000007 #define ll long long struct node { int l,r,w; ll sum; }tree[MAXN<<2]; void Build(int l,int r,int a) { tree[a].l=l; tree[a].r=r; tree[a].w=0; tree[a].sum=0; if(l==r) return ; int mid=(l+r)>>1; Build(l,mid,a<<1); Build(mid+1,r,a<<1|1); } int num; ll Ques(int l,int r,int a1,int b1,int a) { if(a1<=l&&r<=b1) { num=num+tree[a].w; return tree[a].sum; } int mid=(l+r)>>1; ll ans=0; if(a1<=mid) ans=ans+Ques(l,mid,a1,b1,a<<1); if(b1>mid) ans=ans+Ques(mid+1,r,a1,b1,a<<1|1); return ans; } ll z[MAXN]; int ind[MAXN]; void Update(int l,int r,int a1,int a) { if(l==r) { tree[a].w=1; tree[a].sum=l; return ; } int mid=(l+r)>>1; if(a1<=mid) Update(l,mid,a1,a<<1); else Update(mid+1,r,a1,a<<1|1); tree[a].w=tree[a<<1].w+tree[a<<1|1].w; tree[a].sum=tree[a<<1].sum+tree[a<<1|1].sum; } int main() { int n; while(scanf("%d",&n)!=EOF) { Build(1,n,1); for(int i=1;i<=n;i++) scanf("%lld",&z[i]); ll ans=0; for(int i=n;i>=1;i--) { num=0; ll sum=Ques(1,n,1,z[i],1); ans=ans+sum+num*z[i];//+num*z[i]; //printf("%d\n",ans); Update(1,n,z[i],1); } printf("%lld\n",ans); } return 0; }
H
f(n)=f(n-1)+2*f(n-2)+1
f(1)=1
f(2)=2
#include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> using namespace std; #define MAXN 100010 #define inf 1000000007 #define ll long long struct node { ll z[3][3]; }a,b; node mou(node a,node b,int c) { node ans; memset(ans.z,0,sizeof(ans.z)); for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { ll sum=0; for(int k=0;k<3;k++) sum=sum+(a.z[i][k]*b.z[k][j])%c; ans.z[i][j]=sum; } } return ans; } node Quick(node a,int b,int c) { node ans; memset(ans.z,0,sizeof(ans.z)); for(int i=0;i<3;i++) ans.z[i][i]=1; while(b>0) { if(b&1) ans=mou(ans,a,c); b>>=1; a=mou(a,a,c); } return ans; } int main() { int n; while(scanf("%d",&n)!=EOF&&n) { if(n==1) printf("1\n"); else if(n==2) printf("2\n"); else { memset(a.z,0,sizeof(a.z)); a.z[0][1]=2; a.z[1][0]=a.z[1][1]=a.z[2][1]=a.z[2][2]=1; b=Quick(a,n-2,200907); printf("%d\n",(b.z[0][1]+2*b.z[1][1]+b.z[2][1])%200907); } } return 0; }
C
f(n)=(n%10)^f(n/10) f(0)=1
欧拉降幂 A^B%C=A^(B%ph(C)+ph(C)) %C 条件B>=ph(C)
#include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> #include<math.h> using namespace std; #define MAXN 100010 #define inf 1000000007 #define ll long long ll ph(ll a) { ll b=a,c=a,en; en=sqrt(a); for(ll i=2;i<=en;i++) { if(c%i==0) { b=b/i*(i-1); while(c%i==0) c=c/i; } } if(c>1) b=b/c*(c-1); return b; } ll Quick(ll a,ll b,ll c) { ll ans=1; while(b>0) { if(b&1) ans=(ans*a)%c; b>>=1; a=(a*a)%c; } return ans; } ll calc(ll a,ll b,ll mod) { ll ans=1; for(ll i=1;i<=b;i++) { ans=ans*a; if(ans>=mod) return ans; } return ans; } ll f(ll n,ll m) { if(n<10) return n; ll b=f(n/10,ph(m));// ll c=calc(n%10,b,m); if(c>=m) { ll ans=Quick(n%10,b,m); if(ans==0) ans=ans+m; return ans; } return c; } int main() { int t; scanf("%d",&t); while(t--) { ll n,m; scanf("%lld%lld",&n,&m); printf("%lld\n",f(n,m)); } return 0; }
A 页面置换算法 最佳置换算法 大概就是 最久不会使用到的被丢到
先声明一下 我下面的代码是WA的 但是我觉得我是对的 我维护了第i个数字的下次使用的下标然后放到优先队列里维护 不知到为什么错
#include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> #include<math.h> #include<queue> using namespace std; #define MAXN 100010 #define inf 1000000007 #define ll long long int z[MAXN]; int nex[MAXN]; bool vis[MAXN]; int ind[MAXN]; struct node { int w,w1; friend bool operator < (node a,node b) { return a.w>b.w; } }; priority_queue<node>q1; int main() { int c,a,b; while(scanf("%d%d%d",&c,&a,&b)!=EOF) { memset(vis,0,sizeof(vis)); for(int i=1;i<=b;i++) scanf("%d",&z[i]); for(int i=0;i<=b;i++) ind[i]=inf; int ans=0; for(int i=b;i>=1;i--) { nex[i]=ind[z[i]]; ind[z[i]]=i; } while(!q1.empty()) q1.pop(); for(int i=1;i<=b;i++) { int d=z[i]; if(vis[d]) ; else { if(q1.size()>=c) { node n1=q1.top(); q1.pop(); vis[n1.w1]=0; node n; n.w=nex[i]-i; n.w1=z[i]; q1.push(n); vis[d]=1; ans++; } else { node n; n.w=nex[i]-i; n.w1=z[i]; q1.push(n); vis[d]=1; ans++; } } } printf("%d\n",ans); } return 0; }
G
裸的莫比乌斯反演
#include<stdio.h> #define MAXN 100000 bool mark[100005]; int prim[100005]; int mobi[100005]; long long min(long long a,long long b) { return a<b?a:b; } int main() { int T,i,j,k; mobi[1]=1; j=0; for(i=2;i<=MAXN;i++) { if(mark[i]==false) { prim[j++]=i; mobi[i]=-1; } for(k=0;k<j;k++) { if(i*prim[k]>MAXN) break; mark[i*prim[k]]=true; if(i%prim[k]==0) { mobi[i*prim[k]]=0; break; } else mobi[i*prim[k]]=-mobi[i]; } } scanf("%d",&T); j=1; while(T--) { long long a,b,c,d; long long sum,sum2; scanf("%lld%lld",&b,&d); a=c=k=1; sum=0; sum2=0; a=b/k; c=d/k; for(i=1;i<=min(a,c);i++) sum=sum+mobi[i]*(a/i)*(c/i); for(i=1;i<=min(a,c);i++) sum2=sum2+mobi[i]*(min(a,c)/i)*(min(a,c)/i); printf("%lld\n",sum); } return 0; }
J 多重背包 2进制优化 以前写过 就不写了
posted on 2017-05-22 21:18 HelloWorld!--By-MJY 阅读(155) 评论(0) 编辑 收藏 举报