20180110小测

于是我们今天有迎来了一次愉悦的小测。

早晨签到两发大吉,还有一个宜参加模拟赛?buff--。

然后看到了一个暴力分十分良心,怕不是正解不是给人写的了,buf--。

上午上了三节课,书丢了,下课提前走被老师训了,buf--。

中午13:40考试,迟到是必然的,怕不是要变成NOIP了,buf--。

就这样,我迎来了下午的考试。

 

T1:有毒的土豆排序:

 

什么?求逆序对?动态?怕不是树套树?

不行,这样卡n方了。

算了,想想正经方法:

动态维护变化量?写了,对拍,WA了。

肯定是我想的姿势不正确。

用一个树状数组暴力维护。修改的时候用vector记录位置和数值,数值重新排序。

好,70分到手。不管了。

这题目的正解是考虑操作的性质,如果一个数被操作过了那么他后面一定没有比他小的值,然后离线即可。

另外,题面出锅了!必须按照含等于进行计算。我用两次WA证明了这一点。

考场70分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn=1e3+1e2;
 8 
 9 vector<int> poss;
10 int in[maxn],srt[maxn];
11 int n,m,cnt,ans;
12 
13 struct BinaryIndexTree {
14     int dat[maxn];
15     
16     #define lowbit(x) (x&-x)
17     
18     inline void update(int pos,int x) {
19         while( pos <= n )
20             dat[pos] += x,
21             pos += lowbit(pos);
22     }
23     inline int query(int pos) {
24         int ret = 0;
25         while( pos )
26             ret += dat[pos],
27             pos -= lowbit(pos);
28         return ret;
29     }
30     inline void reset() {
31         memset(dat,0,sizeof(dat));
32     }
33 }bit;
34 
35 inline void getposs(int fst) {
36     poss.clear();
37     poss.push_back(fst);
38     for(int i=fst+1;i<=n;i++)
39         if( in[i] < in[fst] )
40             poss.push_back(i);
41 }
42 inline void replac() {
43     static vector<int> nums;
44     nums.clear();
45     for(unsigned i=0;i<poss.size();i++)
46         nums.push_back(in[poss[i]]);
47     sort(nums.begin(),nums.end());
48     for(unsigned i=0;i<poss.size();i++)
49         in[poss[i]] = nums[i];
50 }
51 inline int calc() {
52     int ret = 0;
53     for(int i=1;i<=n;i++) {
54         ret += bit.query(n) - bit.query(in[i]);
55         bit.update(in[i],1);
56     }
57     return ret;
58 }
59 inline void work(int pos) {
60     getposs(pos);
61     replac();
62     bit.reset();
63     ans = calc();
64 }
65 
66 inline void init() {
67     memcpy(srt,in,sizeof(in));
68     cnt = n;
69     sort(srt+1,srt+1+cnt);
70     cnt = unique(srt+1,srt+1+cnt) - srt - 1;
71     for(int i=1;i<=n;i++)
72         in[i] = lower_bound(srt+1,srt+1+cnt,in[i]) - srt;
73     
74     for(int i=1;i<=n;i++)
75         poss.push_back(i);
76     ans = calc();
77 }
78 
79 int main() {
80     scanf("%d%d",&n,&m);
81     for(int i=1;i<=n;i++)
82         scanf("%d",in+i);
83     init();
84     
85     printf("%d\n",ans);
86     for(int j=1,p;j<=m;j++) {
87         scanf("%d",&p);
88         work(p);
89         printf("%d\n",ans);
90     }
91     
92     return 0;
93 }
View Code

 

考后AC代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cctype>
  5 #define lli long long int
  6 #define lowbit(x) (x&-x)
  7 using namespace std;
  8 const int maxn=1e5+1e2;
  9 const int inf=0x3f3f3f3f;
 10 
 11 int in[maxn],srt[maxn],n,m,cnt;
 12 lli iniv[maxn],delt[maxn];
 13 
 14 struct QNode {
 15     int pos,t;
 16     friend bool operator < (const QNode &a,const QNode &b) {
 17         return a.pos < b.pos;
 18     }
 19 }ns[maxn];
 20 
 21 namespace Ini {
 22     lli dat[maxn];
 23     inline void update(int pos,int x) {
 24         while( pos <= n )
 25             dat[pos] += x,
 26             pos += lowbit(pos);
 27     }
 28     inline lli query(int pos) {
 29         lli ret = 0;
 30         while( pos )
 31             ret += dat[pos],
 32             pos -= lowbit(pos);
 33         return ret;
 34     }
 35 }
 36 namespace Bit {
 37     int dat[maxn];
 38     inline void update(int pos,int x) {
 39         while( pos <= cnt )
 40             dat[pos] = min( dat[pos] , x ),
 41             pos += lowbit(pos);
 42     }
 43     inline int query(int pos) {
 44         int ret = *dat;
 45         while( pos )
 46             ret = min( ret , dat[pos] ),
 47             pos -= lowbit(pos);
 48         return ret;
 49     }
 50     inline void init() {
 51         memset(dat,0x3f,sizeof(dat));
 52     }
 53 }
 54 
 55 inline void getans() {
 56     for(int i=n;i;i--) {
 57         Ini::update(in[i],1);
 58         iniv[i] = Ini::query(in[i]-1);
 59         delt[0] += iniv[i];
 60     }
 61     
 62     int pp = 1;
 63     for(int i=1;i<=n;i++) {
 64         while( ns[pp].pos == i ) {
 65             Bit::update(cnt-in[ns[pp].pos]+1,ns[pp].t);
 66             ++pp;
 67         }
 68         int q = Bit::query(cnt-in[i]+1);
 69         if( q != inf ) {
 70             delt[q] -= iniv[i];
 71         }
 72     }
 73     for(int i=1;i<=m;i++)
 74         delt[i] += delt[i-1];
 75 }
 76 
 77 inline void init() {
 78     Bit::init();
 79     
 80     sort(srt+1,srt+1+n);
 81     cnt = unique(srt+1,srt+1+n) - srt - 1;
 82     
 83     for(int i=1;i<=n;i++)
 84         in[i] = lower_bound(srt+1,srt+1+cnt,in[i]) - srt;
 85     
 86     sort(ns+1,ns+1+m);
 87 }
 88 
 89 inline int getint() {
 90     int ret = 0 , ch;
 91     do ch=getchar(); while( !isdigit(ch) );
 92     do ret=ret*10+ch-'0'; while( isdigit(ch=getchar()) );
 93     return ret;
 94 }
 95 int main() {
 96     n = getint() , m = getint();
 97     for(int i=1;i<=n;i++)
 98         srt[i] = in[i] = getint();
 99     for(int i=1;i<=m;i++)
100         ns[i] = (QNode){getint(),i};
101     
102     init();
103     getans();
104     
105     for(int i=0;i<=m;i++)
106         printf("%lld\n",delt[i]);
107     
108     return 0;
109 }
View Code

 

 

T2:窝瓜走路:

 

显然我先写的是这个题。

一看总共9个点,T的范围为long long,矩乘跑不了了。

看一下怎么矩乘,先跑出每对点的方案数,然后再9!枚举哪个点到哪个点。然后方案数连乘更新答案。

100分就这样吧。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define lli long long int
 6 #define debug cout
 7 using namespace std;
 8 const int maxn=12;
 9 const int mod = 1e9+7;
10 
11 const int dx[]={-1,1,0,0,0},dy[]={0,0,-1,1,0};
12 int pre[maxn];
13 lli T,ans,now;
14 
15 struct Matrix {
16     lli dat[maxn][maxn];
17     Matrix(int tpe = 0) {
18         memset(dat,0,sizeof(dat));
19         if( tpe )
20             for(int i=1;i<=9;i++)
21                 dat[i][i] = 1;
22     }
23     friend Matrix operator * (const Matrix &a,const Matrix &b) {
24         Matrix ret;
25         for(int i=1;i<=9;i++)
26             for(int j=1;j<=9;j++)
27                 for(int k=1;k<=9;k++)
28                     ret.dat[i][j] = ( ret.dat[i][j] + a.dat[i][k] * b.dat[k][j] % mod ) % mod;
29         return ret;
30     }
31 }base,way;
32 
33 inline Matrix fastpow(const Matrix &base,lli tme) {
34     Matrix now = base , ret = Matrix(1);
35     while( tme ) {
36         if( tme & 1 )
37             ret = ret * now;
38         now = now * now;
39         tme >>= 1;
40     }
41     return ret;
42 }
43 
44 inline bool judge(int x,int y) {
45     return x > 0 && x <= 3 && y > 0 && y <= 3;
46 }
47 inline int cov(int x,int y) {
48     return ( x - 1 ) * 3 + y;
49 }
50 inline void init() {
51     for(int x=1;x<=3;x++)
52         for(int y=1;y<=3;y++)
53             for(int k=0;k<5;k++) {
54                 const int tx = x + dx[k] , ty = y + dy[k];
55                 if( judge(tx,ty) )
56                     base.dat[cov(tx,ty)][cov(x,y)] = 1;
57             }
58 }
59 
60 inline lli calc() {
61     lli ret = 1;
62     for(int i=1;i<=9;i++)
63         ret = ret * way.dat[i][pre[i]] % mod;
64     return ret;
65 }
66 inline void getans() {
67     init();
68     way = fastpow(base,T);
69     
70     for(int i=1;i<=9;i++)
71         pre[i] = i;
72     
73     do {
74         ans = ( ans + calc() ) % mod;
75     } while( next_permutation(pre+1,pre+10) );
76 }
77 
78 int main() {
79     scanf("%lld",&T);
80     getans();
81     
82     printf("%lld\n",ans);
83     return 0;
84 }
View Code

 

 

T3:不知道起什么名字好的数学题

很显然的题目。

我一开始用μ反演,然后推出了一个可以用nloglogn筛出的东西,70分到手。

然后考虑怎么优化,提取了一个μ的前缀和,还有某个数的k次方的前缀和。

算法复杂度为n^(3/4),然而k次方的前缀和手玩玩不出来,弃坑。

正解:用φ反演。

然后杜教筛φ即可。

对于k次方的前缀和,我们能看出他是一个k+1次的多项式,然后高斯消元求解系数即可。

考场70分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define lli long long int
 6 #define debug cout
 7 using namespace std;
 8 const int maxn=1e6+1e2,lim=1e6;
 9 const int mod=1e9+7;
10 
11 lli sum[maxn];
12 int n,k;
13 
14 inline lli slowpow(lli base) {
15     register lli ret = 1;
16     for(register int i=k;i;i--)
17         ret = ret * base % mod;
18     return ret;
19 }
20 inline void pre() {
21     static lli pows[maxn];
22     static int prime[maxn],mu[maxn],cnt;
23     static unsigned char vis[maxn];
24     
25     mu[1] = 1 , pows[1] = 1;
26     for(lli i=2;i<=n;i++) {
27         if( !vis[i] ) {
28             prime[++cnt] = i,
29             mu[i] = -1 , pows[i] = slowpow(i);
30         }
31         for(int j=1;j<=cnt&&i*prime[j]<=n;j++) {
32             const int tar = i * prime[j];
33             vis[tar] = 1 , pows[tar] = pows[i] * pows[prime[j]] % mod;
34             if( ! ( i % prime[j] ) ) {
35                 mu[tar] = 0;
36                 break;
37             }
38             mu[tar] = -mu[i];
39         }
40     }
41     for(lli i=1;i<=n;i++)
42         if( mu[i] ) {
43             for(lli j=1;i*j<=n;j++)
44                 sum[i*j] += mu[i] * pows[j] % mod ,
45                 sum[i*j] %= mod;
46         }
47     for(int i=1;i<=n;i++)
48         sum[i] = ( ( sum[i] + sum[i-1] ) % mod + mod ) % mod;
49 }
50 
51 inline lli getans() {
52     lli ret = 0;
53     for(lli i=1,j;i<=n;i=j+1) {
54         j = n / ( n / i );
55         ret += ( sum[j] - sum[i-1] ) * ( n / i ) % mod * ( n / i ) % mod;
56         ret %= mod;
57     }
58     return ( ret + mod ) % mod;
59 }
60 
61 int main() {
62     scanf("%d%d",&n,&k);
63     
64     pre();
65     
66     printf("%lld\n",getans());
67     
68     return 0;
69 }
View Code

 

求解系数代码:

  1 #include<bits/stdc++.h>
  2 #define lli long long int
  3 #define debug cout
  4 using namespace std;
  5 const int maxn=100;
  6 const int mod=1e9+7;
  7 
  8 lli f[maxn][maxn];
  9 int k;
 10 
 11 inline lli rev(int base) {
 12     lli now = base , ret = 1 , tme = mod - 2;
 13     while(tme) {
 14         if( tme & 1 )
 15             ret = ret * now % mod;
 16         now = now * now % mod;
 17         tme >>= 1;
 18     }
 19     debug<<"base = "<<base<<"ret = "<<ret<<endl;
 20     return ret;
 21 }
 22 
 23 inline lli slowpow(lli base,int tme) {
 24     lli ret = 1;
 25     for(int t=tme;t;t--)
 26         ret = ret * base % mod;
 27     return ret;
 28 }
 29 inline lli g(lli x) {
 30     lli ret = 0;
 31     for(int i=1;i<=x;i++)
 32         ret =  ( ret + slowpow(i,k-1) ) % mod;
 33     //debug<<"x = "<<x<<"ret = "<<ret<<endl;
 34     return ret;
 35 }
 36 
 37 inline void gen() {
 38     for(int i=1;i<=k+1;i++) {
 39         for(int j=0;j<=k;j++)
 40             f[i][j] = slowpow(i,j);
 41         f[i][k+1] = g(i);
 42     }
 43     for(int i=0;i<=k;i++)
 44         for(int j=0;j<=k+1;j++)
 45             f[i][j] = f[i+1][j];
 46 }
 47 
 48 inline void gauss() {
 49     for(int i=0;i<=k;i++) {
 50         int e = -1;
 51         for(int j=i;j<=k;j++)
 52             if( f[j][i] ) {
 53                 e = j;
 54                 break;
 55             }
 56         if( !~e ) {
 57             puts("Unable to find a solution;");
 58             exit(0);
 59         }
 60         debug<<"i = "<<i<<"e = "<<e<<endl;
 61         if( e != i ) {
 62             for(int j=0;j<=k+1;j++)
 63                 swap(f[i][j],f[e][j]);
 64             e = i;
 65         }
 66         lli r = rev(f[i][i]);
 67         debug<<"fii = "<<f[i][i]<<"rev = "<<r<<endl;
 68         for(int j=0;j<=k+1;j++)
 69             f[i][j] = f[i][j] * r % mod;
 70         for(int j=0;j<=k+1;j++)
 71             debug<<f[i][j]<<" ";debug<<endl;
 72         for(int j=0;j<=k;j++)
 73             if( j != i && f[j][i] ) {
 74                 const lli del = f[j][i];
 75                 for(int t=0;t<=k+1;t++)
 76                     f[j][t] = ( ( f[j][t] - f[i][t] * del % mod ) % mod + mod ) % mod;
 77             }
 78     }
 79 }
 80 
 81 inline void print() {
 82     for(int i=0;i<=k;i++) {
 83         for(int j=0;j<=k+1;j++) debug<<f[i][j]<<" ";debug<<endl;
 84     }
 85 }
 86 int main() {
 87     char com[100];
 88     scanf("%d",&k);
 89     sprintf(com,"dat%d.txt",k);
 90     ++k;
 91     gen();
 92     print();
 93     gauss();
 94     debug<<"Ans = "<<endl;
 95     print();
 96     freopen(com,"w",stdout);
 97     printf("{");
 98     for(int i=0;i<=k;i++)
 99         printf("%lld%c",f[i][k+1],i!=k?',':'}');
100 }
View Code

 

考后AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define lli long long int
 6 #define debug cout
 7 using namespace std;
 8 const int maxn=5e6+1e2,lim=5e6;
 9 const int mod=1e9+7;
10 const int muls[6][7] = {
11     {0,0,0,0,0,0,0},
12     {0,500000004,500000004,0,0,0,0},
13     {0,166666668,500000004,333333336,0,0,0},
14     {0,0,250000002,500000004,250000002,0,0},
15     {0,766666672,0,333333336,500000004,400000003,0},
16     {0,0,916666673,0,416666670,500000004,166666668}
17 };
18 
19 lli sum[maxn],mem[maxn];
20 unsigned char vis[maxn];
21 lli n;
22 int k;
23 
24 inline lli gk(lli x) {
25     x %= mod;
26     lli ret = 0 , now = 1;
27     for(int i=0;i<=k+1;i++) {
28         ret += now * muls[k][i] % mod;
29         ret %= mod;
30         now = now * x % mod;
31     }
32     return ret;
33 }
34 
35 inline void sieve() {
36     static int prime[maxn],cnt;
37     
38     sum[1] = 1;
39     for(lli i=2;i<=lim;i++) {
40         if( !sum[i] ) {
41             prime[++cnt] = i , 
42             sum[i] = i - 1;
43         }
44         for(int j=1;j<=cnt&&i*prime[j]<=lim;j++) {
45             const int tar = i * prime[j];
46             if( ! ( i % prime[j] ) ) {
47                 sum[tar] = sum[i] * prime[j];
48                 break;
49             }
50             sum[tar] = sum[i] * ( prime[j] - 1 );
51         }
52     }
53     for(int i=1;i<=lim;i++)
54         sum[i] += sum[i-1] ,
55         sum[i] %= mod;
56 }
57 
58 inline lli inisum(lli x) {
59     x %= mod;
60     return ( x * ( x + 1 ) >> 1 ) % mod;
61 }
62 inline lli getsum(lli x) {
63     if( x <= lim )
64         return sum[x];
65     const int t = n / x;
66     if( vis[t] )
67         return mem[t];
68     vis[t] = 1 , mem[t] = inisum(x);
69     for(lli i=2,j;i<=x;i=j+1) {
70         j = x / ( x / i );
71         mem[t] -= ( j - i + 1 ) * getsum( x / i ) % mod;
72         mem[t] %= mod;
73     }
74     return mem[t] = ( mem[t] + mod ) % mod;
75 }
76 
77 inline lli calcr(lli x) {
78     lli ret = ( getsum(x) << 1 ) % mod - 1;
79     return ( ret % mod + mod ) % mod;
80 }
81 inline lli getans() {
82     lli ret = 0;
83     for(lli i=1,j;i<=n;i=j+1) {
84         j = n / ( n / i );
85         ret += ( ( gk(j) - gk(i-1) ) % mod + mod ) % mod * calcr( n / i ) % mod;
86         ret %= mod;
87     }
88     return ( ret + mod ) % mod;
89 }
90 
91 int main() {
92     scanf("%lld%d",&n,&k);
93     sieve();
94     
95     printf("%lld\n",getans());
96     
97     return 0;
98 }
View Code

 

最后补一张排名:

为何常数如此之大,然后我掉rank了。

posted @ 2018-01-10 21:59  Cmd2001  阅读(255)  评论(0编辑  收藏  举报