跪求大神帮助解决 fzu 2031 一个数学算法题

Tabris_ 2016-04-07 08:16:11
题目链接 http://acm.fzu.edu.cn/problem.php?pid=2031
Problem 2031 计数问题
Accept: 34 Submit: 251
Time Limit: 2000 mSec Memory Limit : 32768 KB

Problem Description

一个函数f(x) = x^x ,表示x自乘x次之后的结果。例如 f(5) = 5^5 = 3125, f(2) = 2^2 = 4…现在我们定义一个mod操作,表示求模操作。例如 10 mod 3 = 1, 10 mod 7 = 3。(在 C/C++中,mod 操作符为 %, 在Pascal中为mod)。 现在有 g(x,y) = f(x) + f(y) = 0(mod p). 要求找到所有的数对(x,y),满足 (1)1 <= x<= y < p (2)g(x,y) = 0 (mod p) 例如: p = 5, 那么数对 (1,2)是一个解,现在你只需要输出这些数对的个数! 注意: a = b(mod c)实际上是 (a mod c) = (b mod c), 例如 10 = 17(mod 7) 实际上就是(10 mod 7) = (17 mod 7) = 3。
Input

第一行输入一个整数t(t<=100),代表t组测试数据。接下来有t行,每行一组测试数据,每组测试数据输入一个正整数p(2<=p<=10^6,p是一个素数)。
Output

每组测试数据输出一个整数占一行,为所求的数对的个数。
Sample Input

4
2
3
5
7
Sample Output

1
0
2
4
Source

福州大学第八届程序设计竞赛




我的代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
using namespace std;
const int MOD=100000;
int mod[100005],modd[100005],cont;

long long int quickmod(int x,int &n)
{
long long res=1,A=x;
while(x)
{
if(x&1) res=(res*A)%n;
x>>=1;
A=(A*A)%n;
}
return res%n;
}

void init(int &n)
{
for(int i=1; i<n; i++)
{
mod[i]=quickmod(i,n);
}
return ;
}
void solve(int &n)
{
int l=1,r=n-1;
while(l<=r)
{
if(modd[l]==mod[r])
{
// cont++,r--,l++;
int zuo=0,you=0;
for(int i=l;i;i++)
if(modd[i]==modd[l]) zuo++;
else break;
for(int j=r;j;j--)
if(mod[j]==mod[r]) you++;
else break;
cont+=zuo*you;
r-=you,l+=zuo;
}
else if(modd[l]>mod[r])
r--;
else
l++;
/*
r=n;
int summ=mod[l]+mod[r];
if(summ<n) break;
while(r>l)
{
int sum=mod[l]+mod[r--];
if(sum<n) break;
if((sum)%n==0) cont++;
}
*/
}
return ;
}
/*
http://paste.ubuntu.com/15666485/
*/
int main()
{
freopen("in.txt", "r", stdin);
freopen("outtt.txt", "w", stdout);
int t;
scanf("%d",&t);
while(t--)
{
memset(mod,0,sizeof(mod));
int n;
cont=0;
scanf("%d",&n);
init(n);
/*
for(int i=1; i<n; i++)
printf("%d ",mod[i]);
printf("\n");*/
sort(mod+1,mod+n);

for(int i=1; i<n; i++)
modd[i]=n-mod[i];
/*
for(int i=1; i<n; i++)
printf("%d ",mod[i]);
printf("\n");
for(int i=1; i<n; i++)
printf("%d ",modd[i]);
printf("\n");*/
solve(n);
printf("%d,",cont);
}
return 0;
}


...全文
353 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-04-08
  • 打赏
  • 举报
回复
x>>=1; 似应改为 x=(unsigned long long)x>>1;
Tabris_ 2016-04-08
  • 打赏
  • 举报
回复
我的问题judge结果是超时 但是我已经优化到O(N)了 实在不知道是否能有更好的代码 我试过打表 但是100万的数组 导致代码过长 OJ 提交不了 这是一道数论的题目 如果有数论大神 真心希望能帮我看一眼 卡题的感觉跟不好啊
gh_99 2016-04-08
  • 打赏
  • 举报
回复
Sample Input 4 2 //对应输出为0?1? 3 5 7 Sample Output 1 0 2 4 代码如下:
#include <iostream>
#include <cstdio>
/*#include <cstring>*/
#include <algorithm>
/*
#include <cmath>
#include <stack>
#include <queue>
*/
using namespace std;
const int MOD=100000;
int mod[100005],modd[100005],cont;
 
long long int quickmod(int x,int &n)
{
    long long res=1,A=x;
    while(x)
    {
        if(x&1)   res=(res*A)%n;
        x>>=1;
        A=(A*A)%n;
    }
    return res%n;
}
 
void init(int &n)
{
    for(int i=1; i<n; i++)
    {
        mod[i]=quickmod(i,n);
    }
    return ;
}
void solve(int &n)
{
/*    int l=1,r=n-1;
    while(l<=r)
    {
        if(modd[l]==mod[r])
        {
            cont++,r--,l++;
            int zuo=0,you=0;
            for(int i=l;i;i++)
                if(modd[i]==modd[l])   zuo++;
                else     break;
            for(int j=r;j;j--)
                if(mod[j]==mod[r])     you++;
                else     break;
            cont+=zuo*you;
            r-=you,l+=zuo;
        }
        else if(modd[l]>mod[r])
            r--;
        else
            l++;
        /*
        r=n;
        int summ=mod[l]+mod[r];
        if(summ<n) break;
        while(r>l)
        {
            int sum=mod[l]+mod[r--];
            if(sum<n) break;
            if((sum)%n==0) cont++;
        }
        * /
    }*/
	sort(mod+1,mod+n);
	for(int i = 0 ,j = 1; i < n && j < n ; i++)
	{
		while(mod[j] == i)
		{
			modd[i]++;
			j++;
		}
	}
	cont += 2*modd[0]*modd[0];
	for(int i  = 1 ; i < n ; i++)
	{
		cont += modd[i]*modd[n-i];
	}
	cont /= 2;
    return ;
}

int main()
{
/*    freopen("in.txt", "r", stdin);
    freopen("outtt.txt", "w", stdout);
*/    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(mod,0,sizeof(mod));
		memset(modd,0,sizeof(modd));
        int n;
        cont=0;
        scanf("%d",&n);
        init(n);
        /*
        for(int i=1; i<n; i++)
            printf("%d ",mod[i]);
        printf("\n");*/
		/*
        sort(mod+1,mod+n);
 
        for(int i=1; i<n; i++)
            modd[i]=n-mod[i];
		*/
        /*
        for(int i=1; i<n; i++)
            printf("%d ",mod[i]);
        printf("\n");
        for(int i=1; i<n; i++)
            printf("%d ",modd[i]);
        printf("\n");*/
        solve(n);
        printf("%d,",cont);
    }
    return 0;
}
仅供参考.
gh_99 2016-04-08
  • 打赏
  • 举报
回复
引用 楼主 qq_33184171 的回复:
题目链接 http://acm.fzu.edu.cn/problem.php?pid=2031 Problem 2031 计数问题 Accept: 34 Submit: 251 Time Limit: 2000 mSec Memory Limit : 32768 KB Problem Description 一个函数f(x) = x^x ,表示x自乘x次之后的结果。例如 f(5) = 5^5 = 3125, f(2) = 2^2 = 4…现在我们定义一个mod操作,表示求模操作。例如 10 mod 3 = 1, 10 mod 7 = 3。(在 C/C++中,mod 操作符为 %, 在Pascal中为mod)。 现在有 g(x,y) = f(x) + f(y) = 0(mod p). 要求找到所有的数对(x,y),满足 (1)1 <= x<= y < p (2)g(x,y) = 0 (mod p) 例如: p = 5, 那么数对 (1,2)是一个解,现在你只需要输出这些数对的个数! 注意: a = b(mod c)实际上是 (a mod c) = (b mod c), 例如 10 = 17(mod 7) 实际上就是(10 mod 7) = (17 mod 7) = 3。 Input 第一行输入一个整数t(t<=100),代表t组测试数据。接下来有t行,每行一组测试数据,每组测试数据输入一个正整数p(2<=p<=10^6,p是一个素数)。 Output 每组测试数据输出一个整数占一行,为所求的数对的个数。 Sample Input 4 2 3 5 7 Sample Output 1 0 2 4 Source 福州大学第八届程序设计竞赛 我的代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
using namespace std;
const int MOD=100000;
int mod[100005],modd[100005],cont;

long long int quickmod(int x,int &n)
{
    long long res=1,A=x;
    while(x)
    {
        if(x&1)   res=(res*A)%n;
        x>>=1;
        A=(A*A)%n;
    }
    return res%n;
}

void init(int &n)
{
    for(int i=1; i<n; i++)
    {
        mod[i]=quickmod(i,n);
    }
    return ;
}
void solve(int &n)
{
    int l=1,r=n-1;
    while(l<=r)
    {
        if(modd[l]==mod[r])
        {
           // cont++,r--,l++;
            int zuo=0,you=0;
            for(int i=l;i;i++)
                if(modd[i]==modd[l])   zuo++;
                else     break;
            for(int j=r;j;j--)
                if(mod[j]==mod[r])     you++;
                else     break;
            cont+=zuo*you;
            r-=you,l+=zuo;
        }
        else if(modd[l]>mod[r])
            r--;
        else
            l++;
        /*
        r=n;
        int summ=mod[l]+mod[r];
        if(summ<n) break;
        while(r>l)
        {
            int sum=mod[l]+mod[r--];
            if(sum<n) break;
            if((sum)%n==0) cont++;
        }
        */
    }
    return ;
}
/*
http://paste.ubuntu.com/15666485/
*/
int main()
{
    freopen("in.txt", "r", stdin);
    freopen("outtt.txt", "w", stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(mod,0,sizeof(mod));
        int n;
        cont=0;
        scanf("%d",&n);
        init(n);
        /*
        for(int i=1; i<n; i++)
            printf("%d ",mod[i]);
        printf("\n");*/
        sort(mod+1,mod+n);

        for(int i=1; i<n; i++)
            modd[i]=n-mod[i];
        /*
        for(int i=1; i<n; i++)
            printf("%d ",mod[i]);
        printf("\n");
        for(int i=1; i<n; i++)
            printf("%d ",modd[i]);
        printf("\n");*/
        solve(n);
        printf("%d,",cont);
    }
    return 0;
}
2 //对应输出为0 时的代码.

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧