FJUT2019暑假周赛三部分题解

Posted xenny

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FJUT2019暑假周赛三部分题解相关的知识,希望对你有一定的参考价值。

A本来想改到q<1e5,让你们预处理的,然后想了哈作为个逆元模板题吧= =,做不出来自行反思。

B贴个题面

技术图片

因为只有一次机会,那么也就是两点分布期望E = p了,先说说大家的做法,先求出每个n的逆元保存,然后因为技术图片最大只会取到1e6,所以对0-1e6跑一遍每个数的倍数个数。复杂度O(N1/3),代码如下

 

技术图片
 1 #include <iostream>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1000000;
 5 ll sum[maxn+1];
 6 ll sqr3(ll n)
 7     int l=0,r=maxn+1;
 8     while(l+1<r)
 9         ll mid = (l+r)>>1;
10         if(mid*mid*mid>n)
11             r=mid;
12         else l=mid;
13     
14     return l;
15 
16 void exgcd(const ll a, const ll b, ll &g, ll &x, ll &y) 
17     if (!b) g = a, x = 1, y = 0;
18     else exgcd(b, a % b, g, y, x), y -= x * (a / b);
19 
20 
21 ll inv(const ll num,const ll MOD) 
22     ll g, x, y;
23     exgcd(num, MOD, g, x, y);
24     return ((x % MOD) + MOD) % MOD;
25 
26 ll fast_mult(ll x,ll y,ll mod) 
27     ll tmp=(x*y-(ll)((long double)x/mod*y+1.0e-8)*mod);
28     return tmp<0 ? tmp+mod : tmp;
29 
30 int main() 
31     for(ll i=1;i<=maxn;i++)
32         sum[i]=sum[i-1]+((i+1)*(i+1)*(i+1)-1)/i-(i*i*i-1)/i;
33     
34     int T;
35     cin>>T;
36     while(T--)
37         ll n,mod;
38         cin>>n>>mod;
39         ll temp=sqr3(n);
40         ll ans=sum[temp-1]+n/temp-(temp*temp*temp-1)/temp;
41         ans=fast_mult(ans%mod,inv(n,mod)%mod,mod);
42         cout<<ans<<endl;
43     
44     return 0;
45 
View Code

 

然后我的做法是

技术图片

 这里对每一步做一个解释 = =,大佬可以略过,[S]代表艾弗森约定,就是S为真则值为1,否则值为0。

对于第一个等号,就是求这些赢点的个数和。

对于第二个等号,用x来代表k的立方根的底。

对于第三个等号,第一个艾弗森约定应该不难理解,底肯定会小于等于原值。

对于第四个等号,这里第一个和式是处理边界,这里x=N的立方根的底(写错了,懒得重新改了)。这部就是把边界单独处理了。

对于第五个等号,讨论y的取值。

对于第六个等号,换底,然后是对y求和.

后面的同上,讨论取值求和。

最后就可以求得一个公式,因为要求立方根的底,建议用牛顿迭代求解。

最终的复杂度就是O(QlogN)。代码如下

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int q;
 5 ll n,Mod,w;
 6 double newton(double x)
 7     double x1, x2;
 8     if (x == 0.0) return 0.0;
 9     x1 = x;
10     x2 = (2.0 * x1 + x / (x1 * x1)) / 3.0;
11     while (fabs((x2 - x1) / x1) >= 1E-6) 
12         x1 = x2;
13         x2 = (2.0 * x1 + x / (x1 * x1)) / 3.0;
14     
15     return x2;
16 
17 
18 void extgcd(ll a,ll b,ll& x,ll& y)
19     if(!b)
20         x = 1;
21         y = 0;
22         return ;
23     
24     extgcd(b,a%b,y,x);
25     y -= x*(a/b);
26 
27 
28 ll inverse(ll a,ll n)
29     ll x,y;
30     extgcd(a,n,x,y);
31     return (x+n)%n;
32 
33 
34 ll qmul(ll a,ll b) 
35     ll ans = 0;
36     while (b) 
37         if (b&1) 
38             ans = (ans+a)%Mod;
39         
40         a = (a+a)%Mod;
41         b >>= 1;
42     
43     return ans;
44 
45 
46 void solve() 
47     cin >> n >> Mod;
48     ll k = newton(n);
49     ll w = n/k - 3;
50     if (k&1) 
51         w += k*k/2 + 5*k/2 + 1;
52      else 
53         w += k/2*k + k/2*5;
54     
55     //cout << k << ‘ ‘ << w << endl;
56     ll ans = qmul(w%Mod,inverse(n,Mod));
57     cout << ans << endl;
58 
59 
60 int main() 
61     ios_base::sync_with_stdio(0);
62     cin >> q;
63     while (q--) 
64         solve();
65     
66     return 0;
67 
View Code

太伤心了= =,被离线算法吊打。

 

以上是关于FJUT2019暑假周赛三部分题解的主要内容,如果未能解决你的问题,请参考以下文章

SCUACM22暑假集训前劝退赛部分题解

区间最小值 线段树 ( JXNU_ACS 算法组暑假第一次周赛)

暑假N天乐比赛篇 —— 2019杭电暑期多校训练营(第五场)

2019年暑假随笔3

[NEFU ACM大一暑假集训 解题报告]前缀和与差分

暑假爆零欢乐赛SRM08题解