现实生活中,每一个IP段都指向一座城市。为了简化问题,我们将IP段直接看做一个整形数,每座城市也有自己的唯一标识ID,也可以看做一个整数。那么问题来了,现在已知有多个闭区间代表多个IP段,每个区间对应一个城市的ID。现在,小L要查询某个IP属于那个城市,希望聪明的你来帮他完成。
现实生活中,每一个IP段都指向一座城市。为了简化问题,我们将IP段直接看做一个整形数,每座城市也有自己的唯一标识ID,也可以看做一个整数。那么问题来了,现在已知有多个闭区间代表多个IP段,每个区间对应一个城市的ID。现在,小L要查询某个IP属于那个城市,希望聪明的你来帮他完成。
1
2
3 5 99
1 2 77
3
1
3
9
77 99 -1
题目大意:
就是说,给你n个区间和m个询问,然后,每次询问一个数字,看他是不是落在了[l_i,r_i]的区间中。。。
解题思路:
直接给每个区间标号,然后二分就行了。。。二分到有标号的区间,我们就输出区间的ip,没有的话,我们就给个-1.
1 # include<cstdio> 2 # include<iostream> 3 # include<algorithm> 4 5 using namespace std; 6 7 # define MAX 100000+4 8 9 struct node 10 { 11 int left,right; 12 int ip; 13 }a[MAX]; 14 15 int n; 16 17 int cmp ( const struct node & aa,const struct node & bb ) 18 { 19 return aa.left < bb.left; 20 } 21 22 int bsearch ( int val ) 23 { 24 int hi = n; 25 int lo = 1; 26 while ( lo <= hi ) 27 { 28 int mid = (lo+hi)>>1; 29 // cout<<"mid="<<mid<<endl; 30 if ( val >= a[mid].left&&val <= a[mid].right ) 31 { 32 return a[mid].ip; 33 } 34 else if ( a[mid].left > val ) 35 { 36 hi = mid-1; 37 } 38 else if ( a[mid].right < val ) 39 { 40 lo = mid+1; 41 } 42 } 43 return -1; 44 } 45 46 47 int main(void) 48 { 49 int t;scanf("%d",&t); 50 while ( t-- ) 51 { 52 int ans = 0; 53 scanf("%d",&n); 54 for ( int i = 1;i <= n;i++ ) 55 { 56 scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].ip); 57 } 58 sort(a+1,a+n+1,cmp); 59 int m;scanf("%d",&m); 60 while ( m-- ) 61 { 62 int t;scanf("%d",&t); 63 ans = bsearch(t); 64 printf("%d\n",ans); 65 66 } 67 68 } 69 70 71 return 0; 72 }
输出逆序对的个数,且对10^9+7取模
2
3
3 2 1
3
1 2 1
3 1
解题思路:
一开始用bit直接跑,没错,果断直接T了,原因很简单lowbit==0的时候我没有考虑进去。最后看了下数据只有[0,9]果断的跑了暴力(10^6*10)
每次扫一遍,记录这个数字前面有多少个数字比他大。
代码:
1 # include<cstdio> 2 # include<iostream> 3 # include<cstring> 4 5 using namespace std; 6 7 # define MAX 1000004 8 # define MOD 1000000007 9 10 typedef long long LL; 11 12 int a[MAX]; 13 int cnt[MAX]; 14 15 int main(void) 16 { 17 int t;scanf("%d",&t); 18 while ( t-- ) 19 { 20 int n;scanf("%d",&n); 21 for ( int i = 0;i < n;i++ ) 22 { 23 scanf("%d",&a[i]); 24 } 25 LL ans = 0; 26 for ( int i = 0;i < n;i++ ) 27 { 28 for ( int j = a[i]+1;j < 10;j++ ) 29 { 30 ans+=(cnt[j]%MOD); 31 } 32 cnt[a[i]]++; 33 } 34 printf("%d\n",ans%MOD); 35 memset(cnt,0,sizeof(cnt)); 36 } 37 38 39 return 0; 40 }
Boooooom!XDOJ坏掉了!经分析,XDOJ坏掉和一个表达式runid mod oj_tot有关(mod表示取余数,例如10 mod 3=1,5 mod 1=0)。
由于runid可能很大,它被表示成ab的形式。
由于xry111前一天CF打得太晚,现在他完全傻逼了,算不出这个表达式的值。请你写一个程序计算这个值。
数据范围:1<=a, b, oj_tot<=1000
多组数据(不超过1000组),每组数据1行,包括3个整数a、b、oj_tot。
输出一行,包含一个整数ab mod oj_tot。
2 4 100
3 3 3
16
0
解题思路:
直接快速幂取模就OK了。。打个板子上去。
代码:
1 # include<cstdio> 2 # include<iostream> 3 4 using namespace std; 5 6 typedef long long LL; 7 8 int a,b,c; 9 10 int PowerMod( int a,int b,int c ) 11 { 12 int ans = 1; 13 a%=c; 14 while ( b > 0 ) 15 { 16 if ( b&1 ) 17 { 18 ans = ( ans*a)%c; 19 } 20 b/=2; 21 a = (a*a)%c; 22 } 23 return ans; 24 } 25 26 27 int main(void) 28 { 29 while ( scanf("%d%d%d",&a,&b,&c)!=EOF ) 30 { 31 LL res = PowerMod( a,b,c); 32 printf("%lld\n",res); 33 } 34 35 return 0; 36 }
输出最少消耗的能量
1
4
0
2
解题思路:
dp来搞,用dp[i]表示把数字i变成1所需要的最小花费,那么我们写出一个状态转移方程dp[i] = min(dp[i-1],dp[k/prime])+1,把1-1000000内的素数都打出来,然后一个一个除就可以了。
代码:
1 # include<cstdio> 2 # include<iostream> 3 4 using namespace std; 5 6 # define inf 99999999 7 # define MAX 1000000+4 8 9 10 int len; 11 int dp[MAX]; 12 int prime[MAX]; 13 int book[MAX]; 14 15 16 void init() 17 { 18 for ( int i = 2;i < MAX;i++ ) 19 { 20 book[i] = 1; 21 } 22 for ( int i = 2;i < MAX;i++ ) 23 { 24 if ( book[i]==1 ) 25 { 26 for ( int j = 2*i;j < MAX;j+=i ) 27 { 28 book[j] = 0; 29 } 30 } 31 } 32 len = 0; 33 for ( int i = 2;i < MAX;i++ ) 34 { 35 if ( book[i]==1 ) 36 { 37 prime[len++] = i; 38 } 39 } 40 for ( int i = 1;i < MAX;i++ ) 41 dp[i] = inf; 42 dp[1] = 0; 43 for ( int i = 1;i < MAX;i++ ) 44 { 45 for ( int j = 0;j < len;j++ ) 46 { 47 long long t = (long long )i*prime[j]; 48 if ( t>MAX ) 49 break; 50 dp[t] = min(dp[t],dp[i]+1); 51 } 52 dp[i+1] = min(dp[i+1],dp[i]+1); 53 } 54 } 55 56 57 int main(void) 58 { 59 int n; 60 init(); 61 while ( scanf("%d",&n)==1 ) 62 { 63 printf("%d\n",dp[n]); 64 } 65 66 return 0; 67 }
北雷老中医不懂 Fibonacci,于是他定义了一种名叫Feibonaqi的数列,数列满足以下要求:
1.f(0)=0,f(1)=1
2.f(n)=2f(n-1)+f(n-2),n>1
那么问题来了,这个数列的第n项是多少呢?
(不为难大家用高精度了,你只需要将结果对1,000,000,007取模后输出即可)
多组数据
每组数据一行,包含一个整数n,1<n<1,000,000,000
每组数据输出一个整数,即为f(n)对1,000,000,007取模后的结果
2
3
4
2
5
12
解题思路:
矩阵乘法+空间换时间(减少乘法,取模运算)
数列的递推公式为:f(1)=1,f(2)=2,f(n)=f(n-1)+f(n-2)(n>=3)
用矩阵表示为:
进一步,可以得出直接推导公式:
由于矩阵乘法满足结合律,在程序中可以事先给定矩阵的64,32,16,8,4,2,1次方,加快程序的执行时间。(有些题目需要取模运算,也可以事先进行一下)。给定的矩阵次幂,与二进制有关是因为,如下的公式存在解,满足Xi={0或1}:
代码:
1 # include<cstdio> 2 # include<iostream> 3 # include<fstream> 4 5 using namespace std; 6 7 # define MOD 1000000007 8 9 typedef long long LL; 10 11 struct matrix 12 { 13 LL a[2][2]; 14 void init() 15 { 16 a[0][0] = 2; 17 a[0][1] = 1; 18 a[1][0] = 1; 19 a[1][1] = 0; 20 } 21 }; 22 23 int n; 24 25 matrix fun ( matrix aa, matrix bb ) 26 { 27 matrix cc; 28 for ( int i = 0;i < 2;i ++ ) 29 { 30 for ( int j = 0;j < 2;j++ ) 31 { 32 cc.a[i][j] = 0; 33 for ( int k = 0;k < 2;k++ ) 34 { 35 cc.a[i][j]+=(aa.a[i][k]%MOD*bb.a[k][j]%MOD)%MOD; 36 } 37 cc.a[i][j]%=MOD; 38 } 39 } 40 41 return cc; 42 } 43 44 45 46 matrix My_power( matrix aa,int k ) 47 { 48 matrix ans; 49 ans.init(); 50 while ( k >= 1 ) 51 { 52 if ( k&1 ) 53 { 54 ans = fun(ans,aa); 55 } 56 k/=2; 57 aa = fun(aa,aa); 58 } 59 60 return ans; 61 62 } 63 64 65 int main(void) 66 { 67 // freopen("output.txt","w",stdout); 68 int n; 69 70 71 while ( scanf("%d",&n)!=EOF ) 72 { 73 matrix aa; 74 aa.init(); 75 aa = My_power(aa,n-1); 76 printf("%lld\n",aa.a[0][1]%MOD); 77 } 78 79 return 0; 80 } 81