tozangezan's diary

勝手にソースコードをコピペして利用しないでください。

AOJ 2164: Revenge of the Round Table

まあケースあたりO(N^2)くらいのDPをするだけ。
ケースがたくさんあるから最初に全部前計算をtotal O(N^3)未満でやるのかなと思ったら、ケース数が全然なかった。(このせいで無駄に時間を消費した)
テストケース数に強く依存する計算量の問題はケース数とかをちゃんと書くかmultiple testcaseをやめるべきだと思う。

#include<stdio.h>
#include<algorithm>
using namespace std;
long long mod=1000003;
long long inv[1000003];
long long dp[1100][1100];
long long sum[1100][2];
long long dp2[1100][2];
int gcd(int a,int b){
	while(a){
		b%=a;int c=a;a=b;b=c;
	}
	return b;
}
int num[1100];
long long calc(int a,int b){
	if(~dp[a][b])return dp[a][b];
	long long ret=0;
	for(int i=0;i<=a;i++){
		for(int j=0;j<=b;j++)sum[j][0]=sum[j][1]=dp2[j][0]=dp2[j][1]=0;
		dp2[i][0]=1;sum[i][0]=1;
		for(int j=i+1;j<=b;j++){
			dp2[j][1]=(sum[j-1][0]+mod-sum[max(0,j-1-a)][0])%mod;
			if(j==b)dp2[j][0]=(dp2[j][0]+sum[j-1][1]+mod-sum[max(0,j-1-(a-i))][1])%mod;
			else dp2[j][0]=(dp2[j][0]+sum[j-1][1]+mod-sum[max(0,j-1-a)][1])%mod;
			sum[j][0]=(sum[j-1][0]+dp2[j][0])%mod;
			sum[j][1]=(sum[j-1][1]+dp2[j][1])%mod;
		}
		ret=(ret+dp2[b][0]+dp2[b][1])%mod;
	}
	ret=ret*2%mod;
	return dp[a][b]=ret;
}
int main(){
	int a,b;
	inv[1]=1;
	for(int i=2;i<mod;i++)inv[i]=(mod-(mod/i)*inv[mod%i]%mod)%mod;
	for(int i=1;i<1100;i++){
		int c=i;
		int v=2;
		while(c>1){
			if(c%v==0){
				c/=v;num[i]++;
			}else v++;
		}
	}
	for(int i=0;i<1100;i++)for(int j=0;j<1100;j++)dp[i][j]=-1;
	while(scanf("%d%d",&a,&b),a){
		int ad=0;
		if(b>=a)ad=2;
		if(b>=a)b=a-1;
		long long ret=0;
		for(int i=1;i<=a;i++){
			int t=gcd(i,a);
			ret=(ret+calc(min(t-1,b),t))%mod;
		}
		//printf("%lld\n",ret);
		ret=ret*inv[a]%mod;
		printf("%lld\n",(ret+ad)%mod);
	}
}