cf思维+CCPC威海

这篇博客探讨了编程竞赛中涉及的数学和算法技巧。第一部分介绍了如何通过寻找因子和边界条件解决复杂问题,强调了避免直接使用平方根并采用二分逼近的重要性。第二部分讲解了数组处理和快速幂优化在数组统计中的应用,展示了如何优化O(n*m)的时间复杂度。最后一部分讨论了求解圆周率碰撞问题,利用最大公约数和圆心角的关系找到最小步数。
摘要由CSDN通过智能技术生成

B. Ela’s Fitness and the Luxury Number

思路:
对于一个因子x的都有三个数能整除它,分别为x*x x*x+x x*x+2*x。然后去讨论它的边界问题。
一个注意事项:不能用sqrt直接开方,要用二分逼近取下边界。

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\n'
#define ULL unsigned long long
#define down 0.996

using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=1e7+5;
int l,r;
int f(int x){
    int l =0,r=inf;
    while(l<r){
        int mid = l+r+1>>1;
        if((__int128)mid*mid<=x)l=mid;
        else r=mid-1;
    }
    return r;
}
void solve()
{
    cin>>l>>r;
    int a=f(l);
    int b=f(r);
    int ans=(b-a-1)*3;

    int a1=a*a,b1=b*b;
    int a2=a1+a,a3=a1+2*a;
    int b2=b1+b,b3=b1+2*b;

    if(l>a2&&l<=a3) ans++;
    else if(l>a1&&l<=a2) ans+=2;
    else if(l==a1) ans+=3;

    if(r==b3) ans+=3;
    else if(r<b3&&r>=b2) ans+=2;
    else if(r<b2&&r>=b1) ans+=1;


    cout<<ans<<endl;
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

G. Shinyruo and KFC

好废物啊。
思路:
1.O(n*m)的思路肯定过不去。明知道不去想想怎么优化,净想了些乱七八糟的东西。
2.若题目中给出数组a[N]的和不超过一定的量级,则说明数组中不同的数不超过O(logN)
3.相同的数归为一组,然后用快速幂优化就好。笨啊

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e5+5;
const int inf=1e18;
const int mod=998244353;
int n,m,a[N],num[N],cnt;
map<int,int>mp;
int fac[N],inv[N];
int qpow(int a,int b){
    int res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
int getinv(int x){return qpow(x,mod-2);}
int C(int a,int b)
{
    return (fac[a]*inv[a-b]%mod)*inv[b]%mod;
}

void solve()
{
    fac[0]=1;
    for(int i=1;i<=50000;i++) fac[i]=fac[i-1]*i%mod;
    inv[50000]=getinv(fac[50000]);
    for(int i=50000;i>=1;i--) inv[i-1]=inv[i]*i%mod;
    cin>>n>>m;
    int mx=0;
    for(int i=1;i<=n;i++) cin>>a[i],mp[a[i]]++,mx=max(mx,a[i]);
    for(auto x:mp)
        num[++cnt]=x.first;
    for(int i=1;i<=m;i++)
    {
        if(i<mx)
        {
            cout<<0<<endl;continue;
        }
        int ans=1;
        for(int j=1;j<=cnt;j++)
            ans=ans*qpow(C(i,num[j]),mp[num[j]])%mod;
        cout<<ans<<endl;
    }
}
signed main()
{
    //ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;
}

J. Circular Billiard Table

gcd最大公约数这个点没有想到。
得出公式:n*2*(a/b)=360*k,一次碰撞构成的圆心角为2*(a/b),回到原点可能经过k圈。
进一步化简:n=k*(b*180/a),k保证了该式子会是一个整数,那么如何使得n的值最小,
因此可以将式子化简为:180*b/gcd(180*b,a)

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e6+5;
const int inf=1e18;
const int mod=998244353;
//int fac[N],inv[N];
//int qpow(int a,int b){
//    int res=1;
//    while(b)
//    {
//        if(b&1) res=res*a%mod;
//        a=a*a%mod;
//        b>>=1;
//    }
//    return res;
//}
//int getinv(int x){return qpow(x,mod-2);}
//int C(int a,int b)
//{
//    return (fac[a]*inv[a-b]%mod)*inv[b]%mod;
//}
int a,b;

void solve()
{
    cin>>a>>b;
    cout<<b*180/__gcd(180*b,a)-1<<endl;
}
signed main()
{
    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值