飞(fly)(数学推导,liu_runda的神题)

大概看了两三个小时的题解,思考量很大,实现简单........

20分:

明显看出,每个点的贡献是x*(x-1)/2;即组合数C(x,2),从x个线段中选出2个的方案数,显然每次相交贡献为1,n^2枚举相交即可....

40分:

对于四十分,观察图像发现是实际就是求逆序对.....

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<set>
 7 #include<map>
 8 #include<queue>
 9 #define int long long
10 #define MAXN 101001
11 using namespace std;
12 struct node{int x,id;}e[MAXN];
13 int c[MAXN];int N,A,MOD;
14 int lowbit(int x){return x&(-x);}
15 void add(int x)
16 {
17      for(int i=x;i<=N;i+=lowbit(i))
18      {
19          c[i]++;
20      }
21 }
22 int find(int x)
23 {
24      int ans=0;
25      for(int i=x;i>=1;i-=lowbit(i))
26      {
27          ans+=c[i];
28      }
29      return ans;
30 }
31 bool cmp(node a,node b)
32 {
33      return (a.x!=b.x)?a.x<b.x:a.id<b.id;
34 }
35 signed main()
36 {
37     scanf("%lld%lld%lld%lld",&N,&e[1].x,&A,&MOD);e[1].id=1;
38     for(int i=2;i<=N;++i)
39     {
40         e[i].x=(e[i-1].x+A)%MOD;
41         e[i].id=i;
42     }
43     for(int i=1;i<=N;++i)e[i].x++;
44     sort(e+1,e+N+1,cmp);
45     int anss=0;
46     for(int i=1;i<=N;++i)
47     {
48         anss+=find(N)-find(e[i].id);
49         //printf("i=%lld id=%lld anss=%lld
",i,e[i].id,anss);
50         add(e[i].id);
51     }
52     printf("%lld
",anss);
53 }
40分

部分分:

考虑a==x[1]

我们发现图像的一些性质

在x[i]的不断后移中,假设当x[j]时>MOD,

我们发现x[i]-x[j]是一段以a为公差的序列

为了避免枚举n,我们从a入手

因为公差的原因,将序列分成若干个长度为a的段,其实每次经过的点都是一定的

当x<a时

我们直接求解 此时的ans=(i-1)-ask(now)now为当前值,非常明显,因为i-1是所有在它之前出现的数,ask(now)为不符合的....

之后

发现一个小性质,每次后移减少的值是一定的,即ask(a)

然后递推....

100 分:

在上述部分加入x[1]>a的情况

因为每次减的都是ask(a),但这是第一段在1-a中不存在,我们若是按上述方法求,在枚举中不会将

第一段不符合的值减去,那么......我们发现当枚举第二段时(一段就是长度大于mod后重新开始)

当此时长度now大于初始值时,需要减去1,因为这个1无法在ask(1)中得出啦啦啦....

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<set>
 7 #include<map>
 8 #include<queue>
 9 #define int long long
10 #define MAXN 101001
11 using namespace std;
12 int x;
13 int c[MAXN];int N,A,MOD;
14 int lowbit(int x){return x&(-x);}
15 void add(int x)
16 {
17      for(int i=x;i<=A+1;i+=lowbit(i))
18      {
19          c[i]++;
20      }
21 }
22 int find(int x)
23 {
24      int ans=0;
25      for(int i=x;i>=1;i-=lowbit(i))
26      {
27          ans+=c[i];
28      }
29      return ans;
30 }
31 signed main()
32 {
33     scanf("%lld%lld%lld%lld",&N,&x,&A,&MOD);
34     int anss=0;
35     int last=x;
36     int now=(x+A)%MOD;
37     int cas=0;
38     int now_fir=x;//printf("now_fir=%lld
",now_fir);
39     int k=0;
40     for(int i=2;i<=N;++i)
41     {
42         //printf("i=%lld now=%lld last=%lld
",i,now,last);
43         if(now<A)
44         {
45              if(now_fir<=A)
46              {
47                   add(now_fir+1);
48              }
49              now_fir=now;
50              k++;
51              // printf("add last=%lld %lld
",i,now_fir);
52              anss+=(i-1)-find(now+1);
53              cas=(i-1)-find(now+1);
54         }
55         else
56         {
57              cas-=find(A+1); 
58              if(now>=x&&x>A&&k>=1)cas--;
59              anss+=cas;
60         }
61         //printf("anss=%lld
",anss);
62         last=now;
63         now=(now+A)%MOD;
64     }
65     printf("%lld
",anss);
66 }
View Code
原文地址:https://www.cnblogs.com/Wwb123/p/11354911.html