19南京icpc(J、G)

CSDN话题挑战赛第2期

Problem J. Prime Game

思路:
1.计算(1,1)(1,2)(1,3)(1,4)……(1,10)和(2,2)(2,3)(2,4)……(2,10)……每个区间不同的质因子个数。刚开始想使用前缀和的思路,但此时数组最大可开到1e9,这个方法就不行了。
2.因此若看到每个质因子对于它来说有贡献的区间总数,就好思考了很多。
若这个质因子,之前没出现过,则有贡献的区间数为(n-pos+1)*(pos)
若这个质因子,之前出现过,则贡献区间数为(pos-p+1)*(n-pos+1),p为该因子上次出现的下标+1

#include<bits/stdc++.h>
//#define int long long
#define ll 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=1e6+5;
const int inf=1e18;
const int mod=998244353;
int n,a[N];
ll ans;
vector<int>e[N];
void fj(int x,int pos)
{
    if(x==1) return;
    if(x==2)
    {
        e[2].push_back(pos);return;
    }
    if(x==3)
    {
        e[3].push_back(pos);return;
    }
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            e[i].push_back(pos);
            while(x%i==0) x/=i;
        }
    }
    if(x>1)
        e[x].push_back(pos);
}
ll add(int x,int pos)
{
    if(e[x].size())
    {
        int p=e[x].back()+1;
        return (ll)(pos-p+1)*(n-pos+1);
    }
    else
        return (ll)pos*(n-pos+1);
}

void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        int tmp=a[i];
        if(tmp==2||tmp==3)
        {
            ans+=add(tmp,i);fj(a[i],i);continue;
        }
        for(int j=2;j*j<=tmp;j++)
        {
            if(tmp%j==0)
            {
                ans+=add(j,i);
                while(tmp%j==0) tmp/=j;
            }
        }
        if(tmp>1)
            ans+=add(tmp,i);
        fj(a[i],i);
    }
    cout<<ans<<endl;

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

Problem G. Pyramid

打表:模拟坐标系,进行打表找三角形,排列如下:
1 5 15 35 70 126 210 330……
做差如下:
4,10,20,35,56,84,120(第一次)
6,10,15,21,28,36(第二次)
4,5,6,7,8(第三次)
1,1,1,1(第四次)
相当于函数求四次导为常数,可构造曲线y=ax4+bx3+cx2+dx+e
解方程得:a=1/24 , b=6/24, c=11/24, d=6/24, e=0

#include<bits/stdc++.h>
//#define int long long
#define ll 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=1e6+5;
const int inf=1e18;
const int mod=998244353;
int n,cnt;
double sx,sy;
struct node
{
    double x,y;
}e[N];
double cal(int i,int j)
{
    return (e[i].x-e[j].x)*(e[i].x-e[j].x)+(e[i].y-e[j].y)*(e[i].y-e[j].y);
}
int check(int i,int j,int k)
{
    double d1=cal(i,j);
    double d2=cal(i,k);
    double d3=cal(j,k);
    if(abs(d1-d2)<=0.0001&&abs(d1-d3)<=0.0001&&abs(d2-d3)<=0.0001)
        return 1;
    else
        return 0;
}
void solve()
{
    while(cin>>n)
    {
        sx=sy=0;
        cnt=0;
        for(int i=n;i>=0;i--)
        {
            for(int j=0;j<=i;j++)
            {
                e[++cnt].x=sx+j*2;
                e[cnt].y=sy;
            }
            sx+=1;sy+=sqrt(3);
        }
        int ans=0;
        for(int i=1;i<=cnt;i++)
        for(int j=i+1;j<=cnt;j++)
        for(int k=j+1;k<=cnt;k++)
        if(check(i,j,k)==1) ans++;
        cout<<ans<<endl;
    }

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

AC代码:注意对double得处理 注意开longlong 注意取模!!!

#include<bits/stdc++.h>
#define int long long
#define ll 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=1e6+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
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%mod;
}
int getinv(int x){return qpow(x,mod-2);}
int C(int a,int b)
{
    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;
}
int n;
void solve()
{
    cin>>n;
    int g=getinv(24);
    //cout<<g<<endl;
    int ans=((((qpow(n,4)*g%mod+
            qpow(n,3)*6%mod*g%mod))%mod+
            qpow(n,2)*11%mod*g%mod)%mod+
            n*6%mod*g%mod)%mod;
    cout<<ans<<endl;
}
signed main()
{
    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值