結果
問題 | No.1502 Many Simple Additions |
ユーザー | cureskol |
提出日時 | 2022-12-04 10:10:07 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 50 ms / 2,000 ms |
コード長 | 3,513 bytes |
コンパイル時間 | 2,487 ms |
コンパイル使用メモリ | 218,748 KB |
実行使用メモリ | 8,748 KB |
最終ジャッジ日時 | 2024-10-11 09:58:55 |
合計ジャッジ時間 | 4,616 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 1 ms
6,820 KB |
testcase_02 | AC | 2 ms
6,820 KB |
testcase_03 | AC | 2 ms
6,820 KB |
testcase_04 | AC | 2 ms
6,820 KB |
testcase_05 | AC | 2 ms
6,816 KB |
testcase_06 | AC | 2 ms
6,816 KB |
testcase_07 | AC | 2 ms
6,820 KB |
testcase_08 | AC | 2 ms
6,816 KB |
testcase_09 | AC | 2 ms
6,820 KB |
testcase_10 | AC | 2 ms
6,820 KB |
testcase_11 | AC | 2 ms
6,816 KB |
testcase_12 | AC | 2 ms
6,820 KB |
testcase_13 | AC | 2 ms
6,816 KB |
testcase_14 | AC | 2 ms
6,820 KB |
testcase_15 | AC | 2 ms
6,816 KB |
testcase_16 | AC | 2 ms
6,820 KB |
testcase_17 | AC | 2 ms
6,820 KB |
testcase_18 | AC | 2 ms
6,820 KB |
testcase_19 | AC | 2 ms
6,816 KB |
testcase_20 | AC | 2 ms
6,816 KB |
testcase_21 | AC | 1 ms
6,816 KB |
testcase_22 | AC | 2 ms
6,820 KB |
testcase_23 | AC | 2 ms
6,816 KB |
testcase_24 | AC | 2 ms
6,816 KB |
testcase_25 | AC | 2 ms
6,816 KB |
testcase_26 | AC | 2 ms
6,816 KB |
testcase_27 | AC | 40 ms
8,620 KB |
testcase_28 | AC | 39 ms
8,616 KB |
testcase_29 | AC | 13 ms
8,612 KB |
testcase_30 | AC | 49 ms
8,748 KB |
testcase_31 | AC | 49 ms
8,744 KB |
testcase_32 | AC | 50 ms
8,616 KB |
testcase_33 | AC | 36 ms
6,816 KB |
testcase_34 | AC | 37 ms
6,816 KB |
testcase_35 | AC | 37 ms
6,820 KB |
testcase_36 | AC | 29 ms
6,816 KB |
testcase_37 | AC | 30 ms
6,816 KB |
testcase_38 | AC | 3 ms
6,816 KB |
testcase_39 | AC | 2 ms
6,820 KB |
testcase_40 | AC | 5 ms
6,816 KB |
testcase_41 | AC | 6 ms
6,816 KB |
testcase_42 | AC | 21 ms
6,912 KB |
testcase_43 | AC | 2 ms
6,820 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; #define REP(i,n) for(int i=0;i<(n);i++) #include <atcoder/modint> using namespace atcoder; using mint=modint1000000007; ostream& operator<<(ostream &os,mint a){os<<a.val();return os;} istream& operator>>(istream &is,mint &a){ long long b;is>>b;a=b; return is; } class IntegerSumRuleUnionFind{ using ll=long long; int n,num; vector<int> sz,parent; vector<pair<int,ll>> potential; vector<optional<ll>> value; public: IntegerSumRuleUnionFind()=default; IntegerSumRuleUnionFind(int n):n(n),num(n),sz(n,1),parent(n,0),potential(n,{1,0}),value(n,nullopt){ iota(parent.begin(),parent.end(),0); } tuple<int,int,ll> from_root(int x){ if(x==parent[x])return {x,1,0LL}; auto [r,a,b]=from_root(parent[x]); auto [c,d]=potential[x]; parent[x]=r; potential[x]={a*c,b*c+d}; return {r,a*c,b*c+d}; } int leader(int x){ return get<0>(from_root(x)); } bool same(int x,int y){ assert(0<=x and x<n and 0<=y and y<n); return leader(x)==leader(y); } bool merge(int x,int y,ll sum){ // 矛盾する場合は変更はせず false を返す assert(0<=x and x<n and 0<=y and y<n); auto [rx,a,b]=from_root(x); auto [ry,c,d]=from_root(y); if(rx==ry){ // ar+b + cr+d = sum if(a==-c)return b+d==sum; if((sum-b-d)&1)return false; ll r=(sum-b-d)/(a+c); if(value[rx] and value[rx].value()!=r)return false; // これ起きる? value[rx]=r; return true; } if(sz[rx]<sz[ry]){ swap(rx,ry); swap(a,c); swap(b,d); } // a * rx + b + c * ry + d == sum // rx = -c/a ry + (sum-b-d)/a // ry = -a/c rx + (sum-b-d)/c if(value[ry]){ ll k = -c*a * value[ry].value() + (sum-b-d)*a; if(value[rx] and value[rx].value()!=k)return false; value[rx]=k; } sz[rx]+=sz[ry]; parent[ry]=rx; potential[ry]={-a*c,(sum-b-d)*c}; num--; return true; } optional<ll> val(int x){ auto [r,a,b]=from_root(x); if(value[r])return value[r].value()*a+b; return nullopt; } // x と y が隣接してないなら nullopt // x と y が隣接しているが、sum が一意でない場合も nullopt optional<ll> sum(int x,int y){ auto [rx,a,b]=from_root(x); auto [ry,c,d]=from_root(y); if(rx!=ry)return nullopt; if(a==c){ assert(b==d); return nullopt; } return b+d; } int size(const int x){ assert(0<=x and x<n); return sz[leader(x)]; } int count()const{ return num; } }; using ll=long long; void chmin(ll&a,ll b){ a=min(a,b); } void chmax(ll&a,ll b){ a=max(a,b); } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n,m,k;cin>>n>>m>>k; IntegerSumRuleUnionFind UF(n); REP(_,m){ int x,y,z;cin>>x>>y>>z;x--;y--; if(!UF.merge(x,y,z)){ cout<<0<<endl; return 0; } } auto solve=[&](int upper){ vector<ll> low(n,1),high(n,upper); REP(i,n){ auto [r,a,b]=UF.from_root(i); if(UF.val(r)){ ll v=UF.val(r).value()*a+b; if(v<1||upper<v)return mint::raw(0); continue; } // 1 <= ra+b <= upper if(a==1){ chmax(low[r],1-b); chmin(high[r],upper-b); } else{ chmax(low[r],b-upper); chmin(high[r],b-1); } } mint res=1; REP(r,n)if(UF.leader(r)==r and !UF.val(r)) res*=max(high[r]-low[r]+1,0LL); return res; }; cout<< solve(k)-solve(k-1) <<endl; }