intmain(){ cin >> n >> m; for(int i = 0 ; i <= n ; i ++)a[i] = (read() + p) % p; for(int i = 0 ; i <= m ; i ++)b[i] = (read() + p) % p; poly_mul(a , b , n + m); for(int i = 0 ; i <= n + m ; i ++) cout << a[i] << ' '; return0; }
例题(Problem E of The 2021 ICPC Asia Macau Regional Contest)
There are n children playing with n balls. Both children and balls are numbered from 1 to n. Before the game, n integers p1,p2,⋯,pn are given. In each round of the game, child i will pass the ball he possesses to child pi. It is guaranteed that no child will pass his ball to himself, which means pi=i. Moreover, we also know that after each round, each child will hold exactly one ball. Let bi be the ball possessed by child i. At the beginning of the game, child i (1≤i≤n) will be carrying ball i, which means bi=i initially. You’re asked to process q queries. For each query you’re given an integer k and you need to compute the value of i=1∑ni×bi after k rounds. Input There is only one test case for each test file. The first line of the input contains two integers n (2≤n≤105) and q (1≤q≤105), indicating the number of children and the number of queries. The second line contains n integers p1,p2,⋯,pn (1≤pi≤n) indicating how the children pass the balls around. For the following q lines, the i-th line contains one integer ki (1≤ki≤109) indicating a query asking for the result after ki rounds.
#define x first #define y second #define int long long // #define double long double
usingnamespace std;
typedeflonglong LL; typedef pair<int , int> PII;
constint N = 4e5 + 5; constint INF = 0x3f3f3f3f; constint mod = 998244353;
intread(){ int x = 0 , f = 1; char c = getchar(); while(c < '0' || c > '9'){ if(c == '-')f = -1; c = getchar(); } while(c >= '0' && c <= '9'){ x = x * 10 + c - '0'; c = getchar(); } return x * f; }
template <typename T> inlinevoidwrite(T x){ staticint stk[100], top = 0; if (x == 0) return (void)putchar('0'); if (x < 0) x = -x, putchar('-'); while (x) stk[++top] = x % 10, x /= 10; while (top) putchar(stk[top--] + '0'); }
int p[N]; vector<LL> q[N] , s[N]; vector<vector<LL>> f[N];
bool st[N]; vector<int> e[N]; int fa[N]; int len[N];
friendconstexpr Poly operator+(const Poly& a, const Poly& b) { Poly res(std::max(a.size(), b.size())); for (int i = 0; i < a.size(); i++) { res[i] += a[i]; } for (int i = 0; i < b.size(); i++) { res[i] += b[i]; } return res; } friendconstexpr Poly operator*(i64 k, const Poly& a) { Poly ans{}; for (auto i : a) { ans.push_back(k * i); } return ans; }
friendconstexpr Poly operator*(const Poly& a, const Poly& b) { int n = a.size() + b.size() - 1; std::vector<comp> c(norm(n)); for (int i = 0; i < a.size(); i++) { c[i].x = a[i]; } for (int i = 0; i < b.size(); i++) { c[i].y = b[i]; } dft(c); for (auto& x : c) { x = x * x; } idft(c); Poly ans(n); for (int i = 0; i < n; i++) { ans[i] = T(c[i].y * .5L + .5L); } return ans; }
voidsolve(){ int n , t; cin >> n >> t; for(int i = 1 ; i <= n ; i ++)fa[i] = i; for(int i = 1 ; i <= n ; i ++){ cin >> p[i]; e[i].push_back(p[i]); e[p[i]].push_back(i); int pa = find(i) , pb = find(p[i]); if(pa != pb)fa[pa] = pb; } for(int i = 1 ; i <= n ; i ++){ if(st[find(i)] == 0){ dfs(i , -1); } } for(int i = 1 ; i <= n ; i ++){ if(q[i].size() == 0)continue; int k = q[i].size() - 1;
} int cnt = 0; for(int i = 1 ; i <= n ; i ++){ if(f[i].size()){ cnt ++; len[cnt] = i; for(int j = 0 ; j <= i ; j ++)s[cnt].push_back(0); for(auto c : f[i]){ for(int k = 0 ; k < c.size() ; k ++){ // cout << k << ' ' << c[k] << endl; s[cnt][k] += c[k]; } } } } while(t --){ int k; cin >> k; LL res = 0; for(int i = 1 ; i <= cnt ; i ++){ res = (res + s[i][k % len[i]]); } cout << res << endl; } }
signedmain(){ ios; // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); int T = 1; // cin >> T; while(T --){ solve(); } return0; } /* stuff you should look for * int overflow, array bounds * special cases (n=1?) * do smth instead of nothing and stay organized * WRITE STUFF DOWN * DON'T GET STUCK ON ONE APPROACH */