为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

Sgu/491

来自NOCOW
< Sgu
跳转到: 导航, 搜索

题目是说给一个N。让你求有多少对A和B,让方程 Ax+By=N有自然数解。。 首先算出所有小于N的数的因子,一个数的因子个数是 logn级别的。 总共就是NlogN. 先枚举A再枚举x。。然后算出所有可能的B。。然后对于每个A去一次重。。 将所有答案加起来就可以了。。 过的人那么少是因为很多人都错估了暴力枚举的复杂度,是n*logn*logn的。。 Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<ctime>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
const int maxn=100000+1;int n;
vector<int> A[maxn];
typedef vector<int>::iterator it;
typedef vector<int>::reverse_iterator rit;
typedef long long ll;
void Cal(int x)
{
    static int tmp[10000];
    int cnt=0;
    for(int i=1;i*i<=x;i++)if(x%i==0)
        tmp[cnt++]=i,tmp[cnt++]=x/i;
    sort(tmp,tmp+cnt);A[x].push_back(tmp[0]);
    for(int j=1;j<cnt;j++)
        if(tmp[j]!=tmp[j-1])
            A[x].push_back(tmp[j]);
}
int Ans[maxn*50];
int main()
{
    //freopen("in","r",stdin);
    int o=clock();
    cin>>n;
    for(int i=1;i<n;i++) Cal(i);
    int ans=0;
    for(int a=1;a<n;a++)
    {
        int*end=Ans;
        for(int l=a;l<n;l+=a)
        {
            int r=n-l;
            for(rit i=A[r].rbegin();i!=A[r].rend();i++)
                if(*i>a) *(end++)=*i;
                else break;
        }
        if(Ans==end) continue;
        sort(Ans,end);
        ans++;
        for(int*i=Ans+1;i!=end;i++)
            if(*i!=*(i-1)) ans++;
    }
    cout<<ans<<endl;
}
个人工具