今天也算写了点东西,没有偷懒,赶紧写一下今天坑了我一晚上的两个题,一会股市就要开盘了

BZOJ 2818: Gcd

其实这个题一开始五分钟我就把思路想的差不多了。。。

两个数的gcd为素数的意思就是这两个数除以某个素数后的gcd为1,很自然得想到了欧拉函数,然后立即把线性筛的板子贴过来了

我想把素数处理出来,后面基本是枚举素数吧

然后。。。我就跑偏了

我看数据范围1e7,时间给了十秒,结果我就在想可以把每个数跑一遍分别枚举素数递推。。。。

艹。。。其实直接枚举素数就行,反正每两个素数一定互素,所以不相互影响,用欧拉函数的前缀和就可以避免枚举每个素数。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<string>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=1e7,M=1e9+7;
ll phi[N+10];
bool vis[N+10];
ll prime[N+10];
ll miu[N+10];
ll tot;
void init(){
    miu[1]=1;
    tot = 0;
    for(ll i = 2; i <=N; i ++)
    {
        if(!vis[i])
        {
            prime[tot ++] = i;
            phi[i] = i - 1;
            miu[i]=-1;
        }
        for(ll j = 0; j < tot; j ++)
        {
            if(i * prime[j] >= N) break;
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0)
            {
                miu[i*prime[j]]=0;
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else
            {
                phi[i * prime[j]] = phi[i] * phi[prime[j]];
                miu[i*prime[j]]=-1*miu[i];
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int n;
    init();
    cin>>n;
    phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        phi[i]+=phi[i-1];
    }
    ll ans=0;
    for(int i=0;i<=tot;i++)
    {
        int h=n/prime[i];
        if(prime[i]>n)break;
        ans+=phi[h]*2-1;
    }
    cout<<ans<<endl;
}

BZOJ 1452: [JSOI2009]Count

这个题一开始算了算复杂度,直接暴力明明不会超时啊,下面是我暴力结果超时的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<string>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=305,M=1e9+7;
int a[N][N];
int dp[N][N][N];
inline int read()
{
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int main()
{
    //ios::sync_with_stdio(false);
    int n,m;
    //cin>>n>>m;
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>a[i][j];
    int q;
    //cin>>q;
    q=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            for(int k=1;k<=100;k++)
            {
                dp[i][j][k]=dp[i][j-1][k]+dp[i-1][j][k]-dp[i-1][j-1][k];
            }
            dp[i][j][a[i][j]]++;
        }
    while(q--)
    {
        int flag;
        //cin>>flag;
        flag=read();
        if(flag==1){
            int x,y,c;
            //cin>>x>>y>>c;
            x=read(),y=read(),c=read();
            for(int i=x;i<=n;i++)
                for(int j=y;j<=m;j++){
                    dp[i][j][a[x][y]]--;
                    dp[i][j][c]++;
                }
            a[x][y]=c;
        }
        else {
            int x1,x2,y1,y2,c;
            //cin>>x1>>x2>>y1>>y2>>c;
            x1=read(),x2=read(),y1=read(),y2=read(),c=read();
            int ans=dp[x2][y2][c]-dp[x1-1][y2][c]-dp[x2][y1-1][c]+dp[x1-1][y1-1][c];
            //cout<<ans<<endl;
            printf("%d\n",ans);
        }
    }
}

怎么算十秒都应该可以跑出来啊。。。

然后我换上了树状数组,结果还是超时,经过半天的研究发现

我dp数组的第三维从100开到了300,导致交上去连测评都不给你测,直接报超时。。。艹

然后改过来,还是超时。。。

换成scanf和printf,还是超时。。。

终于换成读入挂过了。。。艹,垃圾测评机

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<string>
#include<map>
#include<ctime>
#define ll long long
using namespace std;
const int N=305,M=1e9+7;
int a[N][N];
int dp[N][N][105];
int lowbit(int x)
{
    return x&(-x);
}
int n,m;
inline int read()
{
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}
void change(int x,int y,int c,int v)
{
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=m;j+=lowbit(j))
            dp[i][j][c]+=v;
}
int ask(int x,int y,int c)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            ans+=dp[i][j][c];
    return ans;
}
int main()
{
    //ios::sync_with_stdio(false);
    //cin>>n>>m;
    //scanf("%d%d",&n,&m);
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            //cin>>a[i][j];
            //scanf("%d",&a[i][j]);
            a[i][j]=read();
            change(i,j,a[i][j],1);
        }
    int q;
    //cin>>q;
    //scanf("%d",&q);
    q=read();
    while(q--)
    {
        int flag;
        //cin>>flag;
        //scanf("%d",&flag);
        flag=read();
        if(flag==1){
            int x,y,c;
            //cin>>x>>y>>c;
            //scanf("%d%d%d",&x,&y,&c);
            x=read(),y=read(),c=read();
            /*for(int i=x;i<=n;i++)
                for(int j=y;j<=m;j++){
                    dp[i][j][a[x][y]]--;
                    dp[i][j][c]++;
                }*/
            change(x,y,a[x][y],-1);
            change(x,y,c,1);
            a[x][y]=c;
        }
        else {
            int x1,x2,y1,y2,c;
            //cin>>x1>>x2>>y1>>y2>>c;
            //scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
            x1=read(),x2=read(),y1=read(),y2=read(),c=read();
            //int ans=dp[x2][y2][c]-dp[x1-1][y2][c]-dp[x2][y1-1][c]+dp[x1-1][y1-1][c];
            int ans=ask(x2,y2,c)-ask(x1-1,y2,c)-ask(x2,y1-1,c)+ask(x1-1,y1-1,c);
            printf("%d\n",ans);
        }
    }
}