Submission #107835

# Submission time Handle Problem Language Result Execution time Memory
107835 2019-04-26T02:10:25 Z cki86201 흑백 이미지 찾기 (kriii3_G) C++11
101 / 101
3023 ms 245388 KB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <math.h>
#include <assert.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <algorithm>
#include <iostream>
#include <functional>
#include <unordered_set>
#include <bitset>
#include <time.h>
#include <limits.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define Fi first
#define Se second
#define pb push_back
#define szz(x) (int)x.size()
#define rep(i,n) for(int i=0;i<n;i++)
#define all(x) x.begin(),x.end()
typedef tuple<int, int, int> t3;
 
#include <complex>
typedef double ldouble;
namespace FFT{
	// blog.myungwoo.kr/54
	typedef complex<ldouble> base;
	typedef long long ll;
	
#define sz(x) ((int)(x).size())
 
	const ldouble C_PI = acosl(-1);
 
	void fft(vector <base> &a, bool invert){
		int n = sz(a);
		for(int i=0,j=0;i<n;++i) {
			if(i>j) swap(a[i],a[j]);
			for(int k=n>>1;(j^=k)<k;k>>=1);
		}
		for (int len=2;len<=n;len<<=1){
			ldouble ang = 2*C_PI/len*(invert?-1:1);
			base wlen(cosl(ang), sinl(ang));
			for (int i=0;i<n;i+=len){
				base w(1);
				for (int j=0;j<len/2;j++){
					if((j & 31) == 31)w = base(cosl(ang * j), sinl(ang * j));	//오차가 클 경우 이 빈도를 늘린다. cos, sin 함수는 시간 부담이 있으니 주의
					base u = a[i+j], v = a[i+j+len/2]*w;
					a[i+j] = u+v;
					a[i+j+len/2] = u-v;
					w *= wlen;
				}
			}
		}
		if (invert){
			for (int i=0;i<n;i++) a[i] /= n;
		}
	}
 
	void multiply(const vector<int> &a,const vector<int> &b,vector<int> &res, const int MOD){
		vector <base> fa(all(a)), fb(all(b));
		int n = 1;
		while (n < max(sz(a),sz(b))) n <<= 1; n <<= 1;
		fa.resize(n); fb.resize(n);
		fft(fa,false); fft(fb,false);
		for (int i=0;i<n;i++) fa[i] *= fb[i];
		fft(fa,true);
		res.resize(n);
		for (int i=0;i<n;i++) res[i] = ((ll)(fa[i].real()+(fa[i].real()>0?0.5:-0.5))) % MOD;
	}
 
	void multiply_big(const vector<int> &a,const vector<int> &b, vector <ll> &res){
		// 단순히 오차가 심해 구하지 못하는 경우
		// 결과값은 long long 범위 안
		int n = 1;
		while (n < max(sz(a),sz(b))) n <<= 1; n <<= 1;
		vector <base> A(n), B(n);
		int L_BLOCK = 8;
		for(int i=0;i<n;i++) A[i] = (i < sz(a) ? base(a[i] & ((1<<L_BLOCK)-1), a[i] >> L_BLOCK) : base(0));
		for(int i=0;i<n;i++) B[i] = (i < sz(b) ? base(b[i] & ((1<<L_BLOCK)-1), b[i] >> L_BLOCK) : base(0));
		fft(A, false); fft(B, false);
		vector <base> f1(n), f2(n), f3(n), f4(n);
		for(int i=0;i<n;i++) {
			int j=(n-i)&(n-1);
			f2[i]=(A[i]+conj(A[j]))*base(0.5,0);
			f1[i]=(A[i]-conj(A[j]))*base(0,-0.5);
			f4[i]=(B[i]+conj(B[j]))*base(0.5,0);
			f3[i]=(B[i]-conj(B[j]))*base(0,-0.5);
		}
		for(int i=0;i<n;i++) {
			A[i]=f1[i]*f3[i]+f1[i]*f4[i]*base(0,1);
			B[i]=f2[i]*f4[i]*base(0,1)+f2[i]*f3[i];
		}
		fft(A, true); fft(B, true);
		res.resize(n);
		for(int i=0;i<n;i++) {
        	ll g1=((ll)(A[i].real()+(A[i].real()>0?0.5:-0.5)));
        	ll g2=((ll)(A[i].imag()+(A[i].imag()>0?0.5:-0.5)));
        	ll g3=((ll)(B[i].real()+(B[i].real()>0?0.5:-0.5)));
        	ll g4=((ll)(B[i].imag()+(B[i].imag()>0?0.5:-0.5)));
			res[i] = (g4 + ((g2+g3)<<(L_BLOCK)) + (g1<<(L_BLOCK<<1)));
		}
	}
}
 
int N, M, R, C;
int A[1010][1010], B[1010][1010];
ll Sx[1010][1010], Sxx[1010][1010];
 
vector <int> va, vb;
vector <ll> res;
 
ll get_s(ll T[1010][1010], int x1, int y1, int x2, int y2) {
	return T[x2][y2] - T[x2][y1-1] - T[x1-1][y2] + T[x1-1][y1-1];
}
 
 
 
#define i128 __int128
 
int main() {
	scanf("%d%d", &N, &M);
	for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) scanf("%d", A[i] + j);
	for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) {
		Sx[i][j] = Sx[i-1][j] + Sx[i][j-1] - Sx[i-1][j-1] + A[i][j];
		Sxx[i][j] = Sxx[i-1][j] + Sxx[i][j-1] - Sxx[i-1][j-1] + (ll)A[i][j] * A[i][j];
	}
	scanf("%d%d", &R, &C);
	for(int i=1;i<=R;i++) for(int j=1;j<=C;j++) scanf("%d", B[i] + j);
	ll sy = 0, syy = 0;
	for(int i=1;i<=R;i++) for(int j=1;j<=C;j++) {
		sy += B[i][j];
		syy += (ll) B[i][j] * B[i][j];
	}
	for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) va.pb(A[i][j]);
	for(int i=R;i;i--) {
		for(int j=C;j;j--) vb.pb(B[i][j]);
		rep(j, M - C) vb.pb(0);
	}
	FFT::multiply_big(va, vb, res);
	int ans = 0;
	ll prs[3] = {1000000000000000003ll, 1000000000000000009ll, 1000000000000000031ll};
	for(int i=R;i<=N;i++) for(int j=C;j<=M;j++) {
		ll sxy = res[(i-1)*M+(j-1)];
		ll sx = get_s(Sx, i-R+1, j-C+1, i, j);
		ll sxx = get_s(Sxx, i-R+1, j-C+1, i, j);
		ll n = R * C;
		if((i128)sx * sx == (i128)n * sxx) {
			if((i128)sy * sy == (i128)n * syy) ++ans;
		}
		else {
			int ok = 1;
			rep(u, 3) {
				ll mod = prs[u];
				i128 val = (i128)syy * (((i128)n * sxx - (i128)sx * sx) % mod) % mod;
				val = (val - (i128) sxy * sxy % mod * n) % mod; if(val < 0) val += mod;
				val = (val - (i128) sxx * sy % mod * sy) % mod; if(val < 0) val += mod;
				val = (val + (i128) 2 * sxy * sx % mod * sy) % mod;
				if(val != 0) ok = 0;
			}
			ans += ok;
		}
	}
	printf("%d\n", ans);
	return 0;
}

Compilation message

G.cpp: In function 'void FFT::multiply(const std::vector<int>&, const std::vector<int>&, std::vector<int>&, int)':
G.cpp:71:3: warning: this 'while' clause does not guard... [-Wmisleading-indentation]
   while (n < max(sz(a),sz(b))) n <<= 1; n <<= 1;
   ^~~~~
G.cpp:71:41: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'while'
   while (n < max(sz(a),sz(b))) n <<= 1; n <<= 1;
                                         ^
G.cpp: In function 'void FFT::multiply_big(const std::vector<int>&, const std::vector<int>&, std::vector<long long int>&)':
G.cpp:84:3: warning: this 'while' clause does not guard... [-Wmisleading-indentation]
   while (n < max(sz(a),sz(b))) n <<= 1; n <<= 1;
   ^~~~~
G.cpp:84:41: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'while'
   while (n < max(sz(a),sz(b))) n <<= 1; n <<= 1;
                                         ^
G.cpp: In function 'int main()':
G.cpp:130:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &N, &M);
  ~~~~~^~~~~~~~~~~~~~~~
G.cpp:131:51: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) scanf("%d", A[i] + j);
                                              ~~~~~^~~~~~~~~~~~~~~~
G.cpp:136:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &R, &C);
  ~~~~~^~~~~~~~~~~~~~~~
G.cpp:137:51: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  for(int i=1;i<=R;i++) for(int j=1;j<=C;j++) scanf("%d", B[i] + j);
                                              ~~~~~^~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 36 ms 5112 KB Output is correct
2 Correct 27 ms 5120 KB Output is correct
3 Correct 28 ms 5112 KB Output is correct
4 Correct 30 ms 5112 KB Output is correct
5 Correct 26 ms 5248 KB Output is correct
6 Correct 38 ms 5112 KB Output is correct
7 Correct 31 ms 5240 KB Output is correct
8 Correct 29 ms 5248 KB Output is correct
9 Correct 46 ms 5240 KB Output is correct
10 Correct 29 ms 5240 KB Output is correct
11 Correct 27 ms 5248 KB Output is correct
12 Correct 29 ms 5232 KB Output is correct
13 Correct 30 ms 5348 KB Output is correct
14 Correct 31 ms 5240 KB Output is correct
15 Correct 33 ms 5276 KB Output is correct
16 Correct 44 ms 5232 KB Output is correct
17 Correct 39 ms 5232 KB Output is correct
18 Correct 25 ms 5248 KB Output is correct
19 Correct 31 ms 5240 KB Output is correct
20 Correct 31 ms 5240 KB Output is correct
21 Correct 28 ms 5248 KB Output is correct
22 Correct 29 ms 5240 KB Output is correct
23 Correct 30 ms 5368 KB Output is correct
24 Correct 33 ms 5240 KB Output is correct
25 Correct 31 ms 5380 KB Output is correct
26 Correct 35 ms 5368 KB Output is correct
27 Correct 28 ms 5112 KB Output is correct
28 Correct 28 ms 5368 KB Output is correct
29 Correct 38 ms 5368 KB Output is correct
30 Correct 26 ms 5248 KB Output is correct
31 Correct 28 ms 5368 KB Output is correct
32 Correct 30 ms 5212 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 2706 ms 237848 KB Output is correct
2 Correct 2635 ms 238368 KB Output is correct
3 Correct 2575 ms 238804 KB Output is correct
4 Correct 2875 ms 238132 KB Output is correct
5 Correct 2679 ms 238828 KB Output is correct
6 Correct 2567 ms 238776 KB Output is correct
7 Correct 2608 ms 238812 KB Output is correct
8 Correct 2807 ms 238784 KB Output is correct
9 Correct 3023 ms 238804 KB Output is correct
10 Correct 2851 ms 238940 KB Output is correct
11 Correct 2973 ms 238860 KB Output is correct
12 Correct 2886 ms 238884 KB Output is correct
13 Correct 2285 ms 238988 KB Output is correct
14 Correct 2749 ms 239068 KB Output is correct
15 Correct 2899 ms 238888 KB Output is correct
16 Correct 2524 ms 243536 KB Output is correct
17 Correct 2497 ms 243548 KB Output is correct
18 Correct 2209 ms 243680 KB Output is correct
19 Correct 2357 ms 243668 KB Output is correct
20 Correct 2416 ms 243552 KB Output is correct
21 Correct 2208 ms 243552 KB Output is correct
22 Correct 2237 ms 245388 KB Output is correct
23 Correct 2202 ms 243448 KB Output is correct
24 Correct 2334 ms 243420 KB Output is correct
25 Correct 2448 ms 243472 KB Output is correct
26 Correct 2467 ms 241948 KB Output is correct
27 Correct 2335 ms 243588 KB Output is correct
28 Correct 2873 ms 238892 KB Output is correct
29 Correct 3020 ms 238356 KB Output is correct
30 Correct 2506 ms 237788 KB Output is correct
31 Correct 2374 ms 237724 KB Output is correct
32 Correct 2298 ms 243568 KB Output is correct