zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    1、搭建CICD平台
    Jackson 的 基本用法
    多种方式实现动态替换Android默认桌面Launcher
    Springboot2.x整合Redis以及连接哨兵模式/集群模式
    Redis哨兵(Sentinel)模式
    redis的哨兵模式(redis有密码)
    【数据结构】——LCT(link cut tree)
    征战蓝桥 —— 2017年第八届 —— C/C++A组第3题——魔方状态
    征战蓝桥 —— 2017年第八届 —— C/C++A组第4题——方格分割
    征战蓝桥 —— 2017年第八届 —— C/C++A组第4题——方格分割
  • 原文地址:https://www.cnblogs.com/xenny/p/11365840.html
Copyright © 2011-2022 走看看