被B的0的情况从头卡到尾。导致没看C,心情炸裂又掉分了。
A. Pizza Separation
Students Vasya and Petya are studying at the BSU (Byteland State University). At one of the breaks they decided to order a pizza. In this problem pizza is a circle of some radius. The pizza was delivered already cut into n pieces. The i-th piece is a sector of angle equal to ai. Vasya and Petya want to divide all pieces of pizza into two continuous sectors in such way that the difference between angles of these sectors is minimal. Sector angle is sum of angles of all pieces in it. Pay attention, that one of sectors can be empty.
The first line contains one integer n (1 ≤ n ≤ 360) — the number of pieces into which the delivered pizza was cut.
The second line contains n integers ai (1 ≤ ai ≤ 360) — the angles of the sectors into which the pizza was cut. The sum of all ai is 360.
Print one integer — the minimal difference between angles of sectors that will go to Vasya and Petya.
4
90 90 90 90
0
3
100 100 160
40
1
360
360
4
170 30 150 10
0
In first sample Vasya can take 1 and 2 pieces, Petya can take 3 and 4 pieces. Then the answer is |(90 + 90) - (90 + 90)| = 0.
In third sample there is only one piece of pizza that can be taken by only one from Vasya and Petya. So the answer is |360 - 0| = 360.
In fourth sample Vasya can take 1 and 4 pieces, then Petya will take 2 and 3 pieces. So the answer is |(170 + 10) - (30 + 150)| = 0.
Picture explaning fourth sample:
Both red and green sectors consist of two adjacent pieces of pizza. So Vasya can take green sector, then Petya will take red sector.
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 const int N=1000; 9 int a[N],n,m,all,mindif; 10 set<int> num,num2; 11 set<int>::iterator it; 12 int main() 13 { 14 scanf("%d",&n); 15 all=0; 16 mindif=INF; 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%d",&a[i]); 20 } 21 for(int i=1;i<=n;i++) 22 { 23 all=0; 24 for(int j=i;j<=i+n;j++) 25 { 26 all+=a[(j-1)%n+1]; 27 if(abs(360-2*all)<mindif) 28 mindif=abs(360-2*all); 29 } 30 } 31 printf("%d ",mindif); 32 return 0; 33 }
B. XK Segments
While Vasya finished eating his piece of pizza, the lesson has already started. For being late for the lesson, the teacher suggested Vasya to solve one interesting problem. Vasya has an array a and integer x. He should find the number of different ordered pairs of indexes(i, j) such that ai ≤ aj and there are exactly k integers y such that ai ≤ y ≤ aj and y is divisible by x.
In this problem it is meant that pair (i, j) is equal to (j, i) only if i is equal to j. For example pair (1, 2) is not the same as (2, 1).
The first line contains 3 integers n, x, k (1 ≤ n ≤ 105, 1 ≤ x ≤ 109, 0 ≤ k ≤ 109), where n is the size of the array a and x and k are numbers from the statement.
The second line contains n integers ai (1 ≤ ai ≤ 109) — the elements of the array a.
Print one integer — the answer to the problem.
4 2 1
1 3 5 7
3
4 2 0
5 3 1 7
4
5 3 1
3 3 3 3 3
25
In first sample there are only three suitable pairs of indexes — (1, 2), (2, 3), (3, 4).
In second sample there are four suitable pairs of indexes(1, 1), (2, 2), (3, 3), (4, 4).
In third sample every pair (i, j) is suitable, so the answer is 5 * 5 = 25.
题意:
把左右区间端点分开,那么[l,r]整除x的数的数量为r/x-(l-1)/x。读入的时候把他们(r/x 和(l-1)/x)加入对应的map l和r 中,然后用迭代器it遍历r的map,找对应的 l 中 it->first -k 的数量乘上it->second的数量加入答案中即可。
然后要特判下0的情况,0的话把所有数都加入一个map中,然后遍历这个map,对于每个map对,把他的it->second乘上它前面first/x值为it->first/x的对的个数为答案的贡献。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 #define INF 0x3f3f3f3f 7 using namespace std; 8 const int N=1e5+10; 9 map<LL,LL> r,l,a; 10 map<LL,LL>::iterator it; 11 LL x,k; 12 int n,m,p; 13 LL ans,num; 14 int main() 15 { 16 scanf("%d%I64d%I64d",&n,&x,&k); 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%I64d",&num); 20 l[(num-1)/x]++; 21 r[num/x]++; 22 a[num]++; 23 } 24 ans=0; 25 if(k==0) 26 { 27 p=0; 28 k=0; 29 m=0; 30 for(it=a.begin();it!=a.end();it++) 31 { 32 m+=(int)it->second; 33 if( it->first/x > k) 34 { 35 p=m; 36 if( it->first % x !=0) 37 p-=(int)it->second; 38 } 39 k=it->first/x; 40 ans+=(LL)(m-p) * it->second; 41 } 42 printf("%I64d ",ans); 43 return 0; 44 } 45 for(it=r.begin();it!=r.end();it++) 46 ans+=l[it->first-k]*it->second; 47 printf("%I64d ",ans); 48 return 0; 49 }
题意:
给你n个≤70的数,问有几种取数方式能使取出来的数乘积为完全平方数。
题解:
考虑70内的质因子只有19个。那么每个数字都能表示为19维的01向量,每一维表示该位质因子在该数出现的幂次的奇偶。1为奇0为偶。把他转换为一个二进制数。
那么数的乘积为完全平方数就相当于取这n个19维的01向量的一个组合,使得xor结果为0。
那么写个最高19位的线性基,然后看看线性基里大于0的数的个数lct。答案即为$ 2^{n-lct}-1 $,这是线性基中组合出现相同数的一个结论。
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 const int N=1e5+10; 8 const int M=1e2+10; 9 const LL mod=1e9+7; 10 int prime[M],inf[M],pcnt,n,m,k,p,t; 11 int liner[30],lcnt; 12 LL quick_pow(LL x,LL n) 13 { 14 LL res=1; 15 x%=mod; 16 while(n) 17 { 18 if(n&1) 19 res=(res*x)%mod; 20 n>>=1; 21 x=(x*x)%mod; 22 } 23 return res; 24 } 25 void init() 26 { 27 clr(inf); 28 pcnt=0; 29 lcnt=0; 30 for(int i=2;i<=70;i++) 31 { 32 if(!inf[i]) 33 { 34 prime[++pcnt]=i; 35 inf[i]=1; 36 } 37 for(int j=1;j<=pcnt;j++) 38 { 39 if(i>70/prime[j]) break; 40 inf[prime[j]*i]=1; 41 if(i%prime[j]==0) break; 42 } 43 } 44 clr(liner); 45 return ; 46 } 47 int main() 48 { 49 init(); 50 scanf("%d",&n); 51 for(int i=1;i<=n;i++) 52 { 53 scanf("%d",&p); 54 k=0; 55 for(int j=1;j<=pcnt;j++) 56 { 57 k<<=1; 58 while(!(p%prime[j])) 59 { 60 k^=1; 61 p/=prime[j]; 62 } 63 } 64 for(int j=pcnt;j>=0;j--) 65 { 66 if(k>>j) 67 { 68 if(liner[j]) k^=liner[j]; 69 else 70 { 71 liner[j]=k; 72 break; 73 } 74 } 75 } 76 } 77 for(int i=pcnt;i>=0;i--) 78 if(liner[i]) 79 { 80 lcnt++; 81 } 82 printf("%lld ",(quick_pow(2,(LL)(n-lcnt))-1+mod)%mod); 83 return 0; 84 }