noip2013day1题解

描述

n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推。

游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推,第n − m号位置上的小伙伴走到第 0 号位置,第n-m+1 号位置上的小伙伴走到第 1 号位置,……,第 n-1 号位置上的小伙伴顺时针走到第m-1 号位置。

现在,一共进行了 10^k 轮,请问 x 号小伙伴最后走到了第几号位置。

格式

输入格式

输入共 1 行,包含 4 个整数 n、m、k、x,每两个整数之间用一个空格隔开。

输出格式

输出共 1 行,包含 1 个整数,表示 10^k 轮后 x 号小伙伴所在的位置编号。

样例1

样例输入1[复制]

 
10 3 4 5

样例输出1[复制]

 
5

限制

每个测试点1s。

提示

对于 30%的数据,0 < k < 7;
对于 80%的数据,0 < k < 10^7;
对于 100%的数据,1 < n < 1,000,000,0 < m < n,1 <= x <=n,0 < k < 10^9。

推一推发现是快速幂裸题

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int n,m,k,x;
 5 
 6 int power(int now)
 7 {
 8     if(now==0)return 1;
 9     int t=power(now/2);  
10     t=(t*t)%n;
11     if(now%2!=0)return (t*10)%n;
12     else return t;
13 }
14 
15 
16 int main()
17 {
18     cin>>n>>m>>k>>x;
19     int left=power(k)*m;
20     left%=n;
21     cout<<(left+x)%n;
22     return 0;
23 }

描述

涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:i=1n(aibi)2∑i=1n(ai−bi)2,其中 aiai 表示第一列火柴中第 i 个火柴的高度,bibi 表示第二列火柴中第 i 个火柴的高度。

每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

格式

输入格式

共三行,第一行包含一个整数 n,表示每盒中火柴的数目。

第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。

第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

输出格式

输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果

样例1

样例输入1[复制]

 
4
2 3 1 4
3 2 1 4

样例输出1[复制]

 
1

样例2

样例输入2[复制]

 
4
1 3 4 2
1 7 2 4

样例输出2[复制]

 
2

限制

每个测试点1s。

逆序对,当年的离散化简直exciting

  1 #include<stdio.h> 
  2 #include<iostream>
  3 #include<cstdlib>
  4 using namespace std;
  5 int n,C1[1000000],C2[1000000],A1[1000000],A2[1000000],D1[1000000],tree[1000001]={0},answer=0;
  6 long long S1[1000000],S2[1000000];
  7 
  8 int devide1(int l, int r)
  9 {
 10     int x=S1[(l+r)/2],i=l-1,j=r+1;
 11     while(1)
 12     {
 13         do{--j;}
 14         while(S1[j]>x);
 15 
 16         do{++i;}
 17         while(S1[i]<x);
 18                   
 19         if(i<j)
 20         {
 21             long long t=S1[i];
 22             S1[i]=S1[j];
 23             S1[j]=t;
 24             t=C1[i];
 25             C1[i]=C1[j];
 26             C1[j]=t;
 27         }                   
 28         else return j;
 29     }
 30 }
 31 
 32 void qsort1(int l,int r)
 33 {
 34     int p;
 35     if(l<r)
 36     {
 37         p=devide1(l,r);
 38         qsort1(l,p);
 39         qsort1(p+1,r);
 40     }
 41 }
 42 
 43 int devide2(int l, int r)
 44 {
 45     int x=S2[(l+r)/2],i=l-1,j=r+1;
 46     while(1)
 47     {
 48         do{--j;}
 49         while(S2[j]>x);
 50 
 51         do{++i;}
 52         while(S2[i]<x);
 53                   
 54         if(i<j)
 55         {
 56             long long t=S2[i];
 57             S2[i]=S2[j];
 58             S2[j]=t;
 59             t=C2[i];
 60             C2[i]=C2[j];
 61             C2[j]=t;
 62         }                   
 63         else return j;
 64     }
 65 }
 66 
 67 void qsort2(int l,int r)
 68 {
 69     int p;
 70     if(l<r)
 71     {
 72         p=devide2(l,r);
 73         qsort2(l,p);
 74         qsort2(p+1,r);
 75     }
 76 }
 77 
 78 int read(int k)
 79 {
 80     int sum=0;
 81     while(k)
 82     {
 83         sum+=tree[k];
 84         k-=k&-k;
 85     }
 86     return sum;
 87 }
 88 
 89 void add(int k,int num)
 90 {
 91     while(k<=n)
 92     {
 93         tree[k]+=num;
 94         k+=k&-k;
 95     }
 96 }
 97 
 98 int main()
 99 {
100     cin>>n;
101     for(int i=0;i<n;i++)
102      cin>>S1[i];
103     for(int i=0;i<n;i++)
104     {
105         cin>>S2[i];
106         C1[i]=i;
107         C2[i]=i;
108     }
109     qsort1(0,n-1);
110     qsort2(0,n-1);
111     for(int i=0;i<n;i++)
112     {
113         A1[C1[i]]=i;
114         A2[C2[i]]=i;
115     }
116     for(int i=0;i<n;i++)D1[C1[i]]=C2[i];
117     
118     for(int i=n-1;i>=0;i--)
119     {
120         add(D1[i]+1,1);
121         answer+=(read(D1[i]+1)-1)%99999997;
122         answer%=99999997;
123     }
124     cout<<answer<<endl;
125     return 0;
126 }

描述

A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

格式

输入格式

第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。

接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。

接下来一行有一个整数 q,表示有 q 辆货车需要运货。

接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

输出格式

输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

样例1

样例输入1[复制]

 
4 3 
1 2 4 
2 3 3 
3 1 1 
3
1 3 
1 4 
1 3

样例输出1[复制]

 
3
-1
3

限制

每个测试点1s。

提示

对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q < 1,000;
对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q < 1,000;
对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q < 30,000,0 ≤ z ≤ 100,000。

最小生成树+树上倍增

  1 #include<iostream>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<stdio.h>
  5 #include<cstdlib>
  6 #define N 10005
  7 #define M 50005
  8 #define inf 0x3f3f3f3f
  9 using namespace std;
 10 int n,m,q;
 11 int cnt,tot;
 12 int beg[N];
 13 int deep[N];
 14 int set[N];
 15 int father[N][17],ans[N][17];
 16 int vis[N];
 17 
 18 struct Edge
 19 {
 20     int a,b,weight;
 21 }e[M];
 22 
 23 struct edge
 24 {
 25     int b,next,weight;
 26 }E[N*2];
 27 
 28 int addedge(int a,int b,int weight)
 29 {
 30     E[cnt].b=b;
 31     E[cnt].next=beg[a];
 32     beg[a]=cnt;
 33     E[cnt].weight=weight;
 34     cnt++;
 35     E[cnt].b=a;
 36     E[cnt].next=beg[b];
 37     beg[b]=cnt;
 38     E[cnt].weight=weight;
 39     cnt++;
 40 }
 41 
 42 int find(int a)
 43 {
 44     if(set[a]==a)
 45      return a;
 46     return set[a]=find(set[a]);
 47 }
 48 
 49 int connect(int a,int b)
 50 {
 51     a=find(a),b=find(b);
 52     set[a]=b;
 53 }
 54 
 55 int cmp(Edge a,Edge b)
 56 {
 57     return a.weight<b.weight;
 58 }
 59 
 60 void rebuilt()
 61 {
 62     sort(e,e+m,cmp);
 63     while(m>0)
 64     {
 65         if(find(e[m-1].a)!=find(e[m-1].b))
 66         {
 67             addedge(e[m-1].a-1,e[m-1].b-1,e[m-1].weight);
 68             connect(e[m-1].a,e[m-1].b);
 69         }
 70         m--;
 71     }
 72 }
 73 
 74 void DFS(int x)
 75 {
 76     vis[x]=1;
 77     for(int i=1;i<17;i++)
 78     {
 79         if(deep[x]<(1<<i))break;
 80         father[x][i]=father[father[x][i-1]][i-1];
 81         ans[x][i]=min(ans[x][i-1],ans[father[x][i-1]][i-1]);
 82     }
 83     for(int i=beg[x];i!=-1;i=E[i].next)
 84     {
 85         if(vis[E[i].b]==1)continue;
 86         father[E[i].b][0]=x;
 87         ans[E[i].b][0]=E[i].weight;
 88         deep[E[i].b]=deep[x]+1;
 89         DFS(E[i].b);
 90     }
 91 }
 92 
 93 int lca(int a,int b)
 94 {
 95     if(deep[a]<deep[b])
 96      swap(a,b);
 97     int t=deep[a]-deep[b];
 98     for(int i=0;i<17;i++)
 99      if((1<<i)&t)
100       a=father[a][i];
101     for(int i=16;i>=0;i--)
102      if(father[a][i]!=father[b][i])
103      {
104         a=father[a][i];
105         b=father[b][i];
106      }
107     if(a==b)return a;
108     return father[a][0];
109 }
110 
111 int ask(int a,int b)
112 {
113     int ret=inf;
114     int t=deep[a]-deep[b];
115     for(int i=0;i<17;i++)
116     {
117         if(t&(1<<i))
118         {
119            ret=min(ret,ans[a][i]);
120            a=father[a][i];
121         }
122     }
123     return ret;
124 }
125 
126 int main()
127 {
128     int a,b;
129     memset(beg,-1,sizeof(beg));
130     scanf("%d%d",&n,&m);
131     for(int i=0;i<=n;i++)
132      set[i]=i;
133     for(int i=0;i<m;i++)
134      scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].weight);
135     rebuilt();
136     for(int i=0;i<n;i++)
137      if(vis[i]==0)
138       DFS(i);
139     scanf("%d",&q);
140     for(int i=0;i<q;i++)
141     {
142         scanf("%d%d",&a,&b);
143         if(find(a)!=find(b))
144         {
145              printf("-1\n");
146             continue;
147         }
148         else 
149         {
150             a--,b--;
151             int t=lca(a,b);
152             printf("%d\n",min(ask(a,t),ask(b,t)));
153         }
154     }
155     return 0;
156 }

 

转载于:https://www.cnblogs.com/zyx45889/p/6075335.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值