题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1313
这题的理论就是当且仅当(a,m)=1 时 a*k+b (1<=k<=m) 遍历mod m的完系
一开始的感觉就是暴力 从n/2 开始减 ,直到互素为止,于是直接用java大整数写了:
import java.math.*;
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
Scanner cin=new Scanner(System.in);
int size=cin.nextInt();
for(int l=0;l<size;l++)
{
BigInteger n=cin.nextBigInteger();
BigInteger k=n.divide(new BigInteger("2"));
while(n.gcd(k).compareTo(BigInteger.ONE)!=0)
{
k=k.subtract(BigInteger.ONE);
}
System.out.println(k);
if(l<size-1) System.out.println();
}
}
}
竟然ac了 ,为啥不会超时?
理论解释是,当n=2*k+1 时 ,结果就是k, 当n=4*k时 结果就是2*k-1, 当n=4*k+2 时,结果就是2*k-2, 所以答案都离n/2距离很近,当然就不会超时了。
有了理论的分析 ,用c++也比较简单
但是还是java代码比较简洁~
#include<iostream>
#include<cstring>
using namespace std;
void jminus(int a [],int n,int b)
{
a[n-1]-=b;
for(int i=n-1;i>0;i--)
{
if(a[i]<0)
{
a[i]+=10;
a[i-1]-=1;
}
}
}
void divide(int a [],int n )
{
for(int i=0;i<n-1;i++)
{
if(a[i]%2==0) a[i]=a[i]/2;
else
{
a[i]=a[i]/2;
a[i+1]+=10;
}
}
a[n-1]/=2;
}
int main()
{
int size=0;
cin>>size;
for(int l=0;l<size;l++)
{
char p[2010];
cin>>p;
int n=strlen(p);
int a[n];
for(int i=0;i<n;i++)
a[i]=p[i]-'0';
if(a[n-1]%2==1)
{
divide(a,n);
int start=0;
while(a[start]==0) start++;
for(int i=start;i<n;i++)
cout<<a[i];
cout<<endl;
}
else
{
if(n==1)
{
int temp=a[0];
if(temp%4==2)
{
divide(a,n);
jminus(a,n,2);
}
else
{
divide(a,n);
jminus(a,n,1);
}
}
else
{
int temp=a[n-1]+10*a[n-2];
if(temp%4==2)
{
divide(a,n);
jminus(a,n,2);
}
else
{
divide(a,n);
jminus(a,n,1);
}
}
int start=0;
while(a[start]==0) start++;
for(int i=start;i<n;i++)
cout<<a[i];
cout<<endl;
}
if(l<size-1) cout<<endl;
}
}